run copy.sh

fix test/e2e/disruption after running copy.sh
This commit is contained in:
Chao Xu 2016-10-25 17:30:27 -07:00
parent fd2fdfba89
commit 4287973d99
268 changed files with 61447 additions and 53511 deletions

View File

@ -79,6 +79,14 @@
"Comment": "v2.4.0-rc.1-38-gcd27f17", "Comment": "v2.4.0-rc.1-38-gcd27f17",
"Rev": "cd27f179f2c10c5d300e6d09025b538c475b0d51" "Rev": "cd27f179f2c10c5d300e6d09025b538c475b0d51"
}, },
{
"ImportPath": "github.com/docker/spdystream",
"Rev": "449fdfce4d962303d702fec724ef0ad181c92528"
},
{
"ImportPath": "github.com/docker/spdystream/spdy",
"Rev": "449fdfce4d962303d702fec724ef0ad181c92528"
},
{ {
"ImportPath": "github.com/emicklei/go-restful", "ImportPath": "github.com/emicklei/go-restful",
"Comment": "v1.2-79-g89ef8af", "Comment": "v1.2-79-g89ef8af",

View File

@ -0,0 +1,13 @@
# Contributing to SpdyStream
Want to hack on spdystream? Awesome! Here are instructions to get you
started.
SpdyStream is a part of the [Docker](https://docker.io) project, and follows
the same rules and principles. If you're already familiar with the way
Docker does things, you'll feel right at home.
Otherwise, go read
[Docker's contributions guidelines](https://github.com/dotcloud/docker/blob/master/CONTRIBUTING.md).
Happy hacking!

View File

@ -0,0 +1,191 @@
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
Copyright 2014-2015 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.

View File

@ -0,0 +1,425 @@
Attribution-ShareAlike 4.0 International
=======================================================================
Creative Commons Corporation ("Creative Commons") is not a law firm and
does not provide legal services or legal advice. Distribution of
Creative Commons public licenses does not create a lawyer-client or
other relationship. Creative Commons makes its licenses and related
information available on an "as-is" basis. Creative Commons gives no
warranties regarding its licenses, any material licensed under their
terms and conditions, or any related information. Creative Commons
disclaims all liability for damages resulting from their use to the
fullest extent possible.
Using Creative Commons Public Licenses
Creative Commons public licenses provide a standard set of terms and
conditions that creators and other rights holders may use to share
original works of authorship and other material subject to copyright
and certain other rights specified in the public license below. The
following considerations are for informational purposes only, are not
exhaustive, and do not form part of our licenses.
Considerations for licensors: Our public licenses are
intended for use by those authorized to give the public
permission to use material in ways otherwise restricted by
copyright and certain other rights. Our licenses are
irrevocable. Licensors should read and understand the terms
and conditions of the license they choose before applying it.
Licensors should also secure all rights necessary before
applying our licenses so that the public can reuse the
material as expected. Licensors should clearly mark any
material not subject to the license. This includes other CC-
licensed material, or material used under an exception or
limitation to copyright. More considerations for licensors:
wiki.creativecommons.org/Considerations_for_licensors
Considerations for the public: By using one of our public
licenses, a licensor grants the public permission to use the
licensed material under specified terms and conditions. If
the licensor's permission is not necessary for any reason--for
example, because of any applicable exception or limitation to
copyright--then that use is not regulated by the license. Our
licenses grant only permissions under copyright and certain
other rights that a licensor has authority to grant. Use of
the licensed material may still be restricted for other
reasons, including because others have copyright or other
rights in the material. A licensor may make special requests,
such as asking that all changes be marked or described.
Although not required by our licenses, you are encouraged to
respect those requests where reasonable. More_considerations
for the public:
wiki.creativecommons.org/Considerations_for_licensees
=======================================================================
Creative Commons Attribution-ShareAlike 4.0 International Public
License
By exercising the Licensed Rights (defined below), You accept and agree
to be bound by the terms and conditions of this Creative Commons
Attribution-ShareAlike 4.0 International Public License ("Public
License"). To the extent this Public License may be interpreted as a
contract, You are granted the Licensed Rights in consideration of Your
acceptance of these terms and conditions, and the Licensor grants You
such rights in consideration of benefits the Licensor receives from
making the Licensed Material available under these terms and
conditions.
Section 1 -- Definitions.
a. Adapted Material means material subject to Copyright and Similar
Rights that is derived from or based upon the Licensed Material
and in which the Licensed Material is translated, altered,
arranged, transformed, or otherwise modified in a manner requiring
permission under the Copyright and Similar Rights held by the
Licensor. For purposes of this Public License, where the Licensed
Material is a musical work, performance, or sound recording,
Adapted Material is always produced where the Licensed Material is
synched in timed relation with a moving image.
b. Adapter's License means the license You apply to Your Copyright
and Similar Rights in Your contributions to Adapted Material in
accordance with the terms and conditions of this Public License.
c. BY-SA Compatible License means a license listed at
creativecommons.org/compatiblelicenses, approved by Creative
Commons as essentially the equivalent of this Public License.
d. Copyright and Similar Rights means copyright and/or similar rights
closely related to copyright including, without limitation,
performance, broadcast, sound recording, and Sui Generis Database
Rights, without regard to how the rights are labeled or
categorized. For purposes of this Public License, the rights
specified in Section 2(b)(1)-(2) are not Copyright and Similar
Rights.
e. Effective Technological Measures means those measures that, in the
absence of proper authority, may not be circumvented under laws
fulfilling obligations under Article 11 of the WIPO Copyright
Treaty adopted on December 20, 1996, and/or similar international
agreements.
f. Exceptions and Limitations means fair use, fair dealing, and/or
any other exception or limitation to Copyright and Similar Rights
that applies to Your use of the Licensed Material.
g. License Elements means the license attributes listed in the name
of a Creative Commons Public License. The License Elements of this
Public License are Attribution and ShareAlike.
h. Licensed Material means the artistic or literary work, database,
or other material to which the Licensor applied this Public
License.
i. Licensed Rights means the rights granted to You subject to the
terms and conditions of this Public License, which are limited to
all Copyright and Similar Rights that apply to Your use of the
Licensed Material and that the Licensor has authority to license.
j. Licensor means the individual(s) or entity(ies) granting rights
under this Public License.
k. Share means to provide material to the public by any means or
process that requires permission under the Licensed Rights, such
as reproduction, public display, public performance, distribution,
dissemination, communication, or importation, and to make material
available to the public including in ways that members of the
public may access the material from a place and at a time
individually chosen by them.
l. Sui Generis Database Rights means rights other than copyright
resulting from Directive 96/9/EC of the European Parliament and of
the Council of 11 March 1996 on the legal protection of databases,
as amended and/or succeeded, as well as other essentially
equivalent rights anywhere in the world.
m. You means the individual or entity exercising the Licensed Rights
under this Public License. Your has a corresponding meaning.
Section 2 -- Scope.
a. License grant.
1. Subject to the terms and conditions of this Public License,
the Licensor hereby grants You a worldwide, royalty-free,
non-sublicensable, non-exclusive, irrevocable license to
exercise the Licensed Rights in the Licensed Material to:
a. reproduce and Share the Licensed Material, in whole or
in part; and
b. produce, reproduce, and Share Adapted Material.
2. Exceptions and Limitations. For the avoidance of doubt, where
Exceptions and Limitations apply to Your use, this Public
License does not apply, and You do not need to comply with
its terms and conditions.
3. Term. The term of this Public License is specified in Section
6(a).
4. Media and formats; technical modifications allowed. The
Licensor authorizes You to exercise the Licensed Rights in
all media and formats whether now known or hereafter created,
and to make technical modifications necessary to do so. The
Licensor waives and/or agrees not to assert any right or
authority to forbid You from making technical modifications
necessary to exercise the Licensed Rights, including
technical modifications necessary to circumvent Effective
Technological Measures. For purposes of this Public License,
simply making modifications authorized by this Section 2(a)
(4) never produces Adapted Material.
5. Downstream recipients.
a. Offer from the Licensor -- Licensed Material. Every
recipient of the Licensed Material automatically
receives an offer from the Licensor to exercise the
Licensed Rights under the terms and conditions of this
Public License.
b. Additional offer from the Licensor -- Adapted Material.
Every recipient of Adapted Material from You
automatically receives an offer from the Licensor to
exercise the Licensed Rights in the Adapted Material
under the conditions of the Adapter's License You apply.
c. No downstream restrictions. You may not offer or impose
any additional or different terms or conditions on, or
apply any Effective Technological Measures to, the
Licensed Material if doing so restricts exercise of the
Licensed Rights by any recipient of the Licensed
Material.
6. No endorsement. Nothing in this Public License constitutes or
may be construed as permission to assert or imply that You
are, or that Your use of the Licensed Material is, connected
with, or sponsored, endorsed, or granted official status by,
the Licensor or others designated to receive attribution as
provided in Section 3(a)(1)(A)(i).
b. Other rights.
1. Moral rights, such as the right of integrity, are not
licensed under this Public License, nor are publicity,
privacy, and/or other similar personality rights; however, to
the extent possible, the Licensor waives and/or agrees not to
assert any such rights held by the Licensor to the limited
extent necessary to allow You to exercise the Licensed
Rights, but not otherwise.
2. Patent and trademark rights are not licensed under this
Public License.
3. To the extent possible, the Licensor waives any right to
collect royalties from You for the exercise of the Licensed
Rights, whether directly or through a collecting society
under any voluntary or waivable statutory or compulsory
licensing scheme. In all other cases the Licensor expressly
reserves any right to collect such royalties.
Section 3 -- License Conditions.
Your exercise of the Licensed Rights is expressly made subject to the
following conditions.
a. Attribution.
1. If You Share the Licensed Material (including in modified
form), You must:
a. retain the following if it is supplied by the Licensor
with the Licensed Material:
i. identification of the creator(s) of the Licensed
Material and any others designated to receive
attribution, in any reasonable manner requested by
the Licensor (including by pseudonym if
designated);
ii. a copyright notice;
iii. a notice that refers to this Public License;
iv. a notice that refers to the disclaimer of
warranties;
v. a URI or hyperlink to the Licensed Material to the
extent reasonably practicable;
b. indicate if You modified the Licensed Material and
retain an indication of any previous modifications; and
c. indicate the Licensed Material is licensed under this
Public License, and include the text of, or the URI or
hyperlink to, this Public License.
2. You may satisfy the conditions in Section 3(a)(1) in any
reasonable manner based on the medium, means, and context in
which You Share the Licensed Material. For example, it may be
reasonable to satisfy the conditions by providing a URI or
hyperlink to a resource that includes the required
information.
3. If requested by the Licensor, You must remove any of the
information required by Section 3(a)(1)(A) to the extent
reasonably practicable.
b. ShareAlike.
In addition to the conditions in Section 3(a), if You Share
Adapted Material You produce, the following conditions also apply.
1. The Adapter's License You apply must be a Creative Commons
license with the same License Elements, this version or
later, or a BY-SA Compatible License.
2. You must include the text of, or the URI or hyperlink to, the
Adapter's License You apply. You may satisfy this condition
in any reasonable manner based on the medium, means, and
context in which You Share Adapted Material.
3. You may not offer or impose any additional or different terms
or conditions on, or apply any Effective Technological
Measures to, Adapted Material that restrict exercise of the
rights granted under the Adapter's License You apply.
Section 4 -- Sui Generis Database Rights.
Where the Licensed Rights include Sui Generis Database Rights that
apply to Your use of the Licensed Material:
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
to extract, reuse, reproduce, and Share all or a substantial
portion of the contents of the database;
b. if You include all or a substantial portion of the database
contents in a database in which You have Sui Generis Database
Rights, then the database in which You have Sui Generis Database
Rights (but not its individual contents) is Adapted Material,
including for purposes of Section 3(b); and
c. You must comply with the conditions in Section 3(a) if You Share
all or a substantial portion of the contents of the database.
For the avoidance of doubt, this Section 4 supplements and does not
replace Your obligations under this Public License where the Licensed
Rights include other Copyright and Similar Rights.
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
c. The disclaimer of warranties and limitation of liability provided
above shall be interpreted in a manner that, to the extent
possible, most closely approximates an absolute disclaimer and
waiver of all liability.
Section 6 -- Term and Termination.
a. This Public License applies for the term of the Copyright and
Similar Rights licensed here. However, if You fail to comply with
this Public License, then Your rights under this Public License
terminate automatically.
b. Where Your right to use the Licensed Material has terminated under
Section 6(a), it reinstates:
1. automatically as of the date the violation is cured, provided
it is cured within 30 days of Your discovery of the
violation; or
2. upon express reinstatement by the Licensor.
For the avoidance of doubt, this Section 6(b) does not affect any
right the Licensor may have to seek remedies for Your violations
of this Public License.
c. For the avoidance of doubt, the Licensor may also offer the
Licensed Material under separate terms or conditions or stop
distributing the Licensed Material at any time; however, doing so
will not terminate this Public License.
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
License.
Section 7 -- Other Terms and Conditions.
a. The Licensor shall not be bound by any additional or different
terms or conditions communicated by You unless expressly agreed.
b. Any arrangements, understandings, or agreements regarding the
Licensed Material not stated herein are separate from and
independent of the terms and conditions of this Public License.
Section 8 -- Interpretation.
a. For the avoidance of doubt, this Public License does not, and
shall not be interpreted to, reduce, limit, restrict, or impose
conditions on any use of the Licensed Material that could lawfully
be made without permission under this Public License.
b. To the extent possible, if any provision of this Public License is
deemed unenforceable, it shall be automatically reformed to the
minimum extent necessary to make it enforceable. If the provision
cannot be reformed, it shall be severed from this Public License
without affecting the enforceability of the remaining terms and
conditions.
c. No term or condition of this Public License will be waived and no
failure to comply consented to unless expressly agreed to by the
Licensor.
d. Nothing in this Public License constitutes or may be interpreted
as a limitation upon, or waiver of, any privileges and immunities
that apply to the Licensor or You, including from the legal
processes of any jurisdiction or authority.
=======================================================================
Creative Commons is not a party to its public licenses.
Notwithstanding, Creative Commons may elect to apply one of its public
licenses to material it publishes and in those instances will be
considered the "Licensor." Except for the limited purpose of indicating
that material is shared under a Creative Commons public license or as
otherwise permitted by the Creative Commons policies published at
creativecommons.org/policies, Creative Commons does not authorize the
use of the trademark "Creative Commons" or any other trademark or logo
of Creative Commons without its prior written consent including,
without limitation, in connection with any unauthorized modifications
to any of its public licenses or any other arrangements,
understandings, or agreements concerning use of licensed material. For
the avoidance of doubt, this paragraph does not form part of the public
licenses.
Creative Commons may be contacted at creativecommons.org.

View File

@ -0,0 +1,28 @@
# Spdystream maintainers file
#
# This file describes who runs the docker/spdystream project and how.
# This is a living document - if you see something out of date or missing, speak up!
#
# It is structured to be consumable by both humans and programs.
# To extract its contents programmatically, use any TOML-compliant parser.
#
# This file is compiled into the MAINTAINERS file in docker/opensource.
#
[Org]
[Org."Core maintainers"]
people = [
"dmcgowan",
]
[people]
# A reference list of all people associated with the project.
# All other sections should refer to people by their canonical key
# in the people section.
# ADD YOURSELF HERE IN ALPHABETICAL ORDER
[people.dmcgowan]
Name = "Derek McGowan"
Email = "derek@docker.com"
GitHub = "dmcgowan"

View File

@ -0,0 +1,77 @@
# SpdyStream
A multiplexed stream library using spdy
## Usage
Client example (connecting to mirroring server without auth)
```go
package main
import (
"fmt"
"github.com/docker/spdystream"
"net"
"net/http"
)
func main() {
conn, err := net.Dial("tcp", "localhost:8080")
if err != nil {
panic(err)
}
spdyConn, err := spdystream.NewConnection(conn, false)
if err != nil {
panic(err)
}
go spdyConn.Serve(spdystream.NoOpStreamHandler)
stream, err := spdyConn.CreateStream(http.Header{}, nil, false)
if err != nil {
panic(err)
}
stream.Wait()
fmt.Fprint(stream, "Writing to stream")
buf := make([]byte, 25)
stream.Read(buf)
fmt.Println(string(buf))
stream.Close()
}
```
Server example (mirroring server without auth)
```go
package main
import (
"github.com/docker/spdystream"
"net"
)
func main() {
listener, err := net.Listen("tcp", "localhost:8080")
if err != nil {
panic(err)
}
for {
conn, err := listener.Accept()
if err != nil {
panic(err)
}
spdyConn, err := spdystream.NewConnection(conn, true)
if err != nil {
panic(err)
}
go spdyConn.Serve(spdystream.MirrorStreamHandler)
}
}
```
## Copyright and license
Copyright © 2014-2015 Docker, Inc. All rights reserved, except as follows. Code is released under the Apache 2.0 license. The README.md file, and files in the "docs" folder are licensed under the Creative Commons Attribution 4.0 International License under the terms and conditions set forth in the file "LICENSE.docs". You may obtain a duplicate copy of the same license, titled CC-BY-SA-4.0, at http://creativecommons.org/licenses/by/4.0/.

View File

@ -0,0 +1,958 @@
package spdystream
import (
"errors"
"fmt"
"io"
"net"
"net/http"
"sync"
"time"
"github.com/docker/spdystream/spdy"
)
var (
ErrInvalidStreamId = errors.New("Invalid stream id")
ErrTimeout = errors.New("Timeout occured")
ErrReset = errors.New("Stream reset")
ErrWriteClosedStream = errors.New("Write on closed stream")
)
const (
FRAME_WORKERS = 5
QUEUE_SIZE = 50
)
type StreamHandler func(stream *Stream)
type AuthHandler func(header http.Header, slot uint8, parent uint32) bool
type idleAwareFramer struct {
f *spdy.Framer
conn *Connection
writeLock sync.Mutex
resetChan chan struct{}
setTimeoutLock sync.Mutex
setTimeoutChan chan time.Duration
timeout time.Duration
}
func newIdleAwareFramer(framer *spdy.Framer) *idleAwareFramer {
iaf := &idleAwareFramer{
f: framer,
resetChan: make(chan struct{}, 2),
// setTimeoutChan needs to be buffered to avoid deadlocks when calling setIdleTimeout at about
// the same time the connection is being closed
setTimeoutChan: make(chan time.Duration, 1),
}
return iaf
}
func (i *idleAwareFramer) monitor() {
var (
timer *time.Timer
expired <-chan time.Time
resetChan = i.resetChan
setTimeoutChan = i.setTimeoutChan
)
Loop:
for {
select {
case timeout := <-i.setTimeoutChan:
i.timeout = timeout
if timeout == 0 {
if timer != nil {
timer.Stop()
}
} else {
if timer == nil {
timer = time.NewTimer(timeout)
expired = timer.C
} else {
timer.Reset(timeout)
}
}
case <-resetChan:
if timer != nil && i.timeout > 0 {
timer.Reset(i.timeout)
}
case <-expired:
i.conn.streamCond.L.Lock()
streams := i.conn.streams
i.conn.streams = make(map[spdy.StreamId]*Stream)
i.conn.streamCond.Broadcast()
i.conn.streamCond.L.Unlock()
go func() {
for _, stream := range streams {
stream.resetStream()
}
i.conn.Close()
}()
case <-i.conn.closeChan:
if timer != nil {
timer.Stop()
}
// Start a goroutine to drain resetChan. This is needed because we've seen
// some unit tests with large numbers of goroutines get into a situation
// where resetChan fills up, at least 1 call to Write() is still trying to
// send to resetChan, the connection gets closed, and this case statement
// attempts to grab the write lock that Write() already has, causing a
// deadlock.
//
// See https://github.com/docker/spdystream/issues/49 for more details.
go func() {
for _ = range resetChan {
}
}()
go func() {
for _ = range setTimeoutChan {
}
}()
i.writeLock.Lock()
close(resetChan)
i.resetChan = nil
i.writeLock.Unlock()
i.setTimeoutLock.Lock()
close(i.setTimeoutChan)
i.setTimeoutChan = nil
i.setTimeoutLock.Unlock()
break Loop
}
}
// Drain resetChan
for _ = range resetChan {
}
}
func (i *idleAwareFramer) WriteFrame(frame spdy.Frame) error {
i.writeLock.Lock()
defer i.writeLock.Unlock()
if i.resetChan == nil {
return io.EOF
}
err := i.f.WriteFrame(frame)
if err != nil {
return err
}
i.resetChan <- struct{}{}
return nil
}
func (i *idleAwareFramer) ReadFrame() (spdy.Frame, error) {
frame, err := i.f.ReadFrame()
if err != nil {
return nil, err
}
// resetChan should never be closed since it is only closed
// when the connection has closed its closeChan. This closure
// only occurs after all Reads have finished
// TODO (dmcgowan): refactor relationship into connection
i.resetChan <- struct{}{}
return frame, nil
}
func (i *idleAwareFramer) setIdleTimeout(timeout time.Duration) {
i.setTimeoutLock.Lock()
defer i.setTimeoutLock.Unlock()
if i.setTimeoutChan == nil {
return
}
i.setTimeoutChan <- timeout
}
type Connection struct {
conn net.Conn
framer *idleAwareFramer
closeChan chan bool
goneAway bool
lastStreamChan chan<- *Stream
goAwayTimeout time.Duration
closeTimeout time.Duration
streamLock *sync.RWMutex
streamCond *sync.Cond
streams map[spdy.StreamId]*Stream
nextIdLock sync.Mutex
receiveIdLock sync.Mutex
nextStreamId spdy.StreamId
receivedStreamId spdy.StreamId
pingIdLock sync.Mutex
pingId uint32
pingChans map[uint32]chan error
shutdownLock sync.Mutex
shutdownChan chan error
hasShutdown bool
// for testing https://github.com/docker/spdystream/pull/56
dataFrameHandler func(*spdy.DataFrame) error
}
// NewConnection creates a new spdy connection from an existing
// network connection.
func NewConnection(conn net.Conn, server bool) (*Connection, error) {
framer, framerErr := spdy.NewFramer(conn, conn)
if framerErr != nil {
return nil, framerErr
}
idleAwareFramer := newIdleAwareFramer(framer)
var sid spdy.StreamId
var rid spdy.StreamId
var pid uint32
if server {
sid = 2
rid = 1
pid = 2
} else {
sid = 1
rid = 2
pid = 1
}
streamLock := new(sync.RWMutex)
streamCond := sync.NewCond(streamLock)
session := &Connection{
conn: conn,
framer: idleAwareFramer,
closeChan: make(chan bool),
goAwayTimeout: time.Duration(0),
closeTimeout: time.Duration(0),
streamLock: streamLock,
streamCond: streamCond,
streams: make(map[spdy.StreamId]*Stream),
nextStreamId: sid,
receivedStreamId: rid,
pingId: pid,
pingChans: make(map[uint32]chan error),
shutdownChan: make(chan error),
}
session.dataFrameHandler = session.handleDataFrame
idleAwareFramer.conn = session
go idleAwareFramer.monitor()
return session, nil
}
// Ping sends a ping frame across the connection and
// returns the response time
func (s *Connection) Ping() (time.Duration, error) {
pid := s.pingId
s.pingIdLock.Lock()
if s.pingId > 0x7ffffffe {
s.pingId = s.pingId - 0x7ffffffe
} else {
s.pingId = s.pingId + 2
}
s.pingIdLock.Unlock()
pingChan := make(chan error)
s.pingChans[pid] = pingChan
defer delete(s.pingChans, pid)
frame := &spdy.PingFrame{Id: pid}
startTime := time.Now()
writeErr := s.framer.WriteFrame(frame)
if writeErr != nil {
return time.Duration(0), writeErr
}
select {
case <-s.closeChan:
return time.Duration(0), errors.New("connection closed")
case err, ok := <-pingChan:
if ok && err != nil {
return time.Duration(0), err
}
break
}
return time.Now().Sub(startTime), nil
}
// Serve handles frames sent from the server, including reply frames
// which are needed to fully initiate connections. Both clients and servers
// should call Serve in a separate goroutine before creating streams.
func (s *Connection) Serve(newHandler StreamHandler) {
// use a WaitGroup to wait for all frames to be drained after receiving
// go-away.
var wg sync.WaitGroup
// Parition queues to ensure stream frames are handled
// by the same worker, ensuring order is maintained
frameQueues := make([]*PriorityFrameQueue, FRAME_WORKERS)
for i := 0; i < FRAME_WORKERS; i++ {
frameQueues[i] = NewPriorityFrameQueue(QUEUE_SIZE)
// Ensure frame queue is drained when connection is closed
go func(frameQueue *PriorityFrameQueue) {
<-s.closeChan
frameQueue.Drain()
}(frameQueues[i])
wg.Add(1)
go func(frameQueue *PriorityFrameQueue) {
// let the WaitGroup know this worker is done
defer wg.Done()
s.frameHandler(frameQueue, newHandler)
}(frameQueues[i])
}
var (
partitionRoundRobin int
goAwayFrame *spdy.GoAwayFrame
)
Loop:
for {
readFrame, err := s.framer.ReadFrame()
if err != nil {
if err != io.EOF {
fmt.Errorf("frame read error: %s", err)
} else {
debugMessage("(%p) EOF received", s)
}
break
}
var priority uint8
var partition int
switch frame := readFrame.(type) {
case *spdy.SynStreamFrame:
if s.checkStreamFrame(frame) {
priority = frame.Priority
partition = int(frame.StreamId % FRAME_WORKERS)
debugMessage("(%p) Add stream frame: %d ", s, frame.StreamId)
s.addStreamFrame(frame)
} else {
debugMessage("(%p) Rejected stream frame: %d ", s, frame.StreamId)
continue
}
case *spdy.SynReplyFrame:
priority = s.getStreamPriority(frame.StreamId)
partition = int(frame.StreamId % FRAME_WORKERS)
case *spdy.DataFrame:
priority = s.getStreamPriority(frame.StreamId)
partition = int(frame.StreamId % FRAME_WORKERS)
case *spdy.RstStreamFrame:
priority = s.getStreamPriority(frame.StreamId)
partition = int(frame.StreamId % FRAME_WORKERS)
case *spdy.HeadersFrame:
priority = s.getStreamPriority(frame.StreamId)
partition = int(frame.StreamId % FRAME_WORKERS)
case *spdy.PingFrame:
priority = 0
partition = partitionRoundRobin
partitionRoundRobin = (partitionRoundRobin + 1) % FRAME_WORKERS
case *spdy.GoAwayFrame:
// hold on to the go away frame and exit the loop
goAwayFrame = frame
break Loop
default:
priority = 7
partition = partitionRoundRobin
partitionRoundRobin = (partitionRoundRobin + 1) % FRAME_WORKERS
}
frameQueues[partition].Push(readFrame, priority)
}
close(s.closeChan)
// wait for all frame handler workers to indicate they've drained their queues
// before handling the go away frame
wg.Wait()
if goAwayFrame != nil {
s.handleGoAwayFrame(goAwayFrame)
}
// now it's safe to close remote channels and empty s.streams
s.streamCond.L.Lock()
// notify streams that they're now closed, which will
// unblock any stream Read() calls
for _, stream := range s.streams {
stream.closeRemoteChannels()
}
s.streams = make(map[spdy.StreamId]*Stream)
s.streamCond.Broadcast()
s.streamCond.L.Unlock()
}
func (s *Connection) frameHandler(frameQueue *PriorityFrameQueue, newHandler StreamHandler) {
for {
popFrame := frameQueue.Pop()
if popFrame == nil {
return
}
var frameErr error
switch frame := popFrame.(type) {
case *spdy.SynStreamFrame:
frameErr = s.handleStreamFrame(frame, newHandler)
case *spdy.SynReplyFrame:
frameErr = s.handleReplyFrame(frame)
case *spdy.DataFrame:
frameErr = s.dataFrameHandler(frame)
case *spdy.RstStreamFrame:
frameErr = s.handleResetFrame(frame)
case *spdy.HeadersFrame:
frameErr = s.handleHeaderFrame(frame)
case *spdy.PingFrame:
frameErr = s.handlePingFrame(frame)
case *spdy.GoAwayFrame:
frameErr = s.handleGoAwayFrame(frame)
default:
frameErr = fmt.Errorf("unhandled frame type: %T", frame)
}
if frameErr != nil {
fmt.Errorf("frame handling error: %s", frameErr)
}
}
}
func (s *Connection) getStreamPriority(streamId spdy.StreamId) uint8 {
stream, streamOk := s.getStream(streamId)
if !streamOk {
return 7
}
return stream.priority
}
func (s *Connection) addStreamFrame(frame *spdy.SynStreamFrame) {
var parent *Stream
if frame.AssociatedToStreamId != spdy.StreamId(0) {
parent, _ = s.getStream(frame.AssociatedToStreamId)
}
stream := &Stream{
streamId: frame.StreamId,
parent: parent,
conn: s,
startChan: make(chan error),
headers: frame.Headers,
finished: (frame.CFHeader.Flags & spdy.ControlFlagUnidirectional) != 0x00,
replyCond: sync.NewCond(new(sync.Mutex)),
dataChan: make(chan []byte),
headerChan: make(chan http.Header),
closeChan: make(chan bool),
}
if frame.CFHeader.Flags&spdy.ControlFlagFin != 0x00 {
stream.closeRemoteChannels()
}
s.addStream(stream)
}
// checkStreamFrame checks to see if a stream frame is allowed.
// If the stream is invalid, then a reset frame with protocol error
// will be returned.
func (s *Connection) checkStreamFrame(frame *spdy.SynStreamFrame) bool {
s.receiveIdLock.Lock()
defer s.receiveIdLock.Unlock()
if s.goneAway {
return false
}
validationErr := s.validateStreamId(frame.StreamId)
if validationErr != nil {
go func() {
resetErr := s.sendResetFrame(spdy.ProtocolError, frame.StreamId)
if resetErr != nil {
fmt.Errorf("reset error: %s", resetErr)
}
}()
return false
}
return true
}
func (s *Connection) handleStreamFrame(frame *spdy.SynStreamFrame, newHandler StreamHandler) error {
stream, ok := s.getStream(frame.StreamId)
if !ok {
return fmt.Errorf("Missing stream: %d", frame.StreamId)
}
newHandler(stream)
return nil
}
func (s *Connection) handleReplyFrame(frame *spdy.SynReplyFrame) error {
debugMessage("(%p) Reply frame received for %d", s, frame.StreamId)
stream, streamOk := s.getStream(frame.StreamId)
if !streamOk {
debugMessage("Reply frame gone away for %d", frame.StreamId)
// Stream has already gone away
return nil
}
if stream.replied {
// Stream has already received reply
return nil
}
stream.replied = true
// TODO Check for error
if (frame.CFHeader.Flags & spdy.ControlFlagFin) != 0x00 {
s.remoteStreamFinish(stream)
}
close(stream.startChan)
return nil
}
func (s *Connection) handleResetFrame(frame *spdy.RstStreamFrame) error {
stream, streamOk := s.getStream(frame.StreamId)
if !streamOk {
// Stream has already been removed
return nil
}
s.removeStream(stream)
stream.closeRemoteChannels()
if !stream.replied {
stream.replied = true
stream.startChan <- ErrReset
close(stream.startChan)
}
stream.finishLock.Lock()
stream.finished = true
stream.finishLock.Unlock()
return nil
}
func (s *Connection) handleHeaderFrame(frame *spdy.HeadersFrame) error {
stream, streamOk := s.getStream(frame.StreamId)
if !streamOk {
// Stream has already gone away
return nil
}
if !stream.replied {
// No reply received...Protocol error?
return nil
}
// TODO limit headers while not blocking (use buffered chan or goroutine?)
select {
case <-stream.closeChan:
return nil
case stream.headerChan <- frame.Headers:
}
if (frame.CFHeader.Flags & spdy.ControlFlagFin) != 0x00 {
s.remoteStreamFinish(stream)
}
return nil
}
func (s *Connection) handleDataFrame(frame *spdy.DataFrame) error {
debugMessage("(%p) Data frame received for %d", s, frame.StreamId)
stream, streamOk := s.getStream(frame.StreamId)
if !streamOk {
debugMessage("(%p) Data frame gone away for %d", s, frame.StreamId)
// Stream has already gone away
return nil
}
if !stream.replied {
debugMessage("(%p) Data frame not replied %d", s, frame.StreamId)
// No reply received...Protocol error?
return nil
}
debugMessage("(%p) (%d) Data frame handling", stream, stream.streamId)
if len(frame.Data) > 0 {
stream.dataLock.RLock()
select {
case <-stream.closeChan:
debugMessage("(%p) (%d) Data frame not sent (stream shut down)", stream, stream.streamId)
case stream.dataChan <- frame.Data:
debugMessage("(%p) (%d) Data frame sent", stream, stream.streamId)
}
stream.dataLock.RUnlock()
}
if (frame.Flags & spdy.DataFlagFin) != 0x00 {
s.remoteStreamFinish(stream)
}
return nil
}
func (s *Connection) handlePingFrame(frame *spdy.PingFrame) error {
if s.pingId&0x01 != frame.Id&0x01 {
return s.framer.WriteFrame(frame)
}
pingChan, pingOk := s.pingChans[frame.Id]
if pingOk {
close(pingChan)
}
return nil
}
func (s *Connection) handleGoAwayFrame(frame *spdy.GoAwayFrame) error {
debugMessage("(%p) Go away received", s)
s.receiveIdLock.Lock()
if s.goneAway {
s.receiveIdLock.Unlock()
return nil
}
s.goneAway = true
s.receiveIdLock.Unlock()
if s.lastStreamChan != nil {
stream, _ := s.getStream(frame.LastGoodStreamId)
go func() {
s.lastStreamChan <- stream
}()
}
// Do not block frame handler waiting for closure
go s.shutdown(s.goAwayTimeout)
return nil
}
func (s *Connection) remoteStreamFinish(stream *Stream) {
stream.closeRemoteChannels()
stream.finishLock.Lock()
if stream.finished {
// Stream is fully closed, cleanup
s.removeStream(stream)
}
stream.finishLock.Unlock()
}
// CreateStream creates a new spdy stream using the parameters for
// creating the stream frame. The stream frame will be sent upon
// calling this function, however this function does not wait for
// the reply frame. If waiting for the reply is desired, use
// the stream Wait or WaitTimeout function on the stream returned
// by this function.
func (s *Connection) CreateStream(headers http.Header, parent *Stream, fin bool) (*Stream, error) {
// MUST synchronize stream creation (all the way to writing the frame)
// as stream IDs **MUST** increase monotonically.
s.nextIdLock.Lock()
defer s.nextIdLock.Unlock()
streamId := s.getNextStreamId()
if streamId == 0 {
return nil, fmt.Errorf("Unable to get new stream id")
}
stream := &Stream{
streamId: streamId,
parent: parent,
conn: s,
startChan: make(chan error),
headers: headers,
dataChan: make(chan []byte),
headerChan: make(chan http.Header),
closeChan: make(chan bool),
}
debugMessage("(%p) (%p) Create stream", s, stream)
s.addStream(stream)
return stream, s.sendStream(stream, fin)
}
func (s *Connection) shutdown(closeTimeout time.Duration) {
// TODO Ensure this isn't called multiple times
s.shutdownLock.Lock()
if s.hasShutdown {
s.shutdownLock.Unlock()
return
}
s.hasShutdown = true
s.shutdownLock.Unlock()
var timeout <-chan time.Time
if closeTimeout > time.Duration(0) {
timeout = time.After(closeTimeout)
}
streamsClosed := make(chan bool)
go func() {
s.streamCond.L.Lock()
for len(s.streams) > 0 {
debugMessage("Streams opened: %d, %#v", len(s.streams), s.streams)
s.streamCond.Wait()
}
s.streamCond.L.Unlock()
close(streamsClosed)
}()
var err error
select {
case <-streamsClosed:
// No active streams, close should be safe
err = s.conn.Close()
case <-timeout:
// Force ungraceful close
err = s.conn.Close()
// Wait for cleanup to clear active streams
<-streamsClosed
}
if err != nil {
duration := 10 * time.Minute
time.AfterFunc(duration, func() {
select {
case err, ok := <-s.shutdownChan:
if ok {
fmt.Errorf("Unhandled close error after %s: %s", duration, err)
}
default:
}
})
s.shutdownChan <- err
}
close(s.shutdownChan)
return
}
// Closes spdy connection by sending GoAway frame and initiating shutdown
func (s *Connection) Close() error {
s.receiveIdLock.Lock()
if s.goneAway {
s.receiveIdLock.Unlock()
return nil
}
s.goneAway = true
s.receiveIdLock.Unlock()
var lastStreamId spdy.StreamId
if s.receivedStreamId > 2 {
lastStreamId = s.receivedStreamId - 2
}
goAwayFrame := &spdy.GoAwayFrame{
LastGoodStreamId: lastStreamId,
Status: spdy.GoAwayOK,
}
err := s.framer.WriteFrame(goAwayFrame)
if err != nil {
return err
}
go s.shutdown(s.closeTimeout)
return nil
}
// CloseWait closes the connection and waits for shutdown
// to finish. Note the underlying network Connection
// is not closed until the end of shutdown.
func (s *Connection) CloseWait() error {
closeErr := s.Close()
if closeErr != nil {
return closeErr
}
shutdownErr, ok := <-s.shutdownChan
if ok {
return shutdownErr
}
return nil
}
// Wait waits for the connection to finish shutdown or for
// the wait timeout duration to expire. This needs to be
// called either after Close has been called or the GOAWAYFRAME
// has been received. If the wait timeout is 0, this function
// will block until shutdown finishes. If wait is never called
// and a shutdown error occurs, that error will be logged as an
// unhandled error.
func (s *Connection) Wait(waitTimeout time.Duration) error {
var timeout <-chan time.Time
if waitTimeout > time.Duration(0) {
timeout = time.After(waitTimeout)
}
select {
case err, ok := <-s.shutdownChan:
if ok {
return err
}
case <-timeout:
return ErrTimeout
}
return nil
}
// NotifyClose registers a channel to be called when the remote
// peer inidicates connection closure. The last stream to be
// received by the remote will be sent on the channel. The notify
// timeout will determine the duration between go away received
// and the connection being closed.
func (s *Connection) NotifyClose(c chan<- *Stream, timeout time.Duration) {
s.goAwayTimeout = timeout
s.lastStreamChan = c
}
// SetCloseTimeout sets the amount of time close will wait for
// streams to finish before terminating the underlying network
// connection. Setting the timeout to 0 will cause close to
// wait forever, which is the default.
func (s *Connection) SetCloseTimeout(timeout time.Duration) {
s.closeTimeout = timeout
}
// SetIdleTimeout sets the amount of time the connection may sit idle before
// it is forcefully terminated.
func (s *Connection) SetIdleTimeout(timeout time.Duration) {
s.framer.setIdleTimeout(timeout)
}
func (s *Connection) sendHeaders(headers http.Header, stream *Stream, fin bool) error {
var flags spdy.ControlFlags
if fin {
flags = spdy.ControlFlagFin
}
headerFrame := &spdy.HeadersFrame{
StreamId: stream.streamId,
Headers: headers,
CFHeader: spdy.ControlFrameHeader{Flags: flags},
}
return s.framer.WriteFrame(headerFrame)
}
func (s *Connection) sendReply(headers http.Header, stream *Stream, fin bool) error {
var flags spdy.ControlFlags
if fin {
flags = spdy.ControlFlagFin
}
replyFrame := &spdy.SynReplyFrame{
StreamId: stream.streamId,
Headers: headers,
CFHeader: spdy.ControlFrameHeader{Flags: flags},
}
return s.framer.WriteFrame(replyFrame)
}
func (s *Connection) sendResetFrame(status spdy.RstStreamStatus, streamId spdy.StreamId) error {
resetFrame := &spdy.RstStreamFrame{
StreamId: streamId,
Status: status,
}
return s.framer.WriteFrame(resetFrame)
}
func (s *Connection) sendReset(status spdy.RstStreamStatus, stream *Stream) error {
return s.sendResetFrame(status, stream.streamId)
}
func (s *Connection) sendStream(stream *Stream, fin bool) error {
var flags spdy.ControlFlags
if fin {
flags = spdy.ControlFlagFin
stream.finished = true
}
var parentId spdy.StreamId
if stream.parent != nil {
parentId = stream.parent.streamId
}
streamFrame := &spdy.SynStreamFrame{
StreamId: spdy.StreamId(stream.streamId),
AssociatedToStreamId: spdy.StreamId(parentId),
Headers: stream.headers,
CFHeader: spdy.ControlFrameHeader{Flags: flags},
}
return s.framer.WriteFrame(streamFrame)
}
// getNextStreamId returns the next sequential id
// every call should produce a unique value or an error
func (s *Connection) getNextStreamId() spdy.StreamId {
sid := s.nextStreamId
if sid > 0x7fffffff {
return 0
}
s.nextStreamId = s.nextStreamId + 2
return sid
}
// PeekNextStreamId returns the next sequential id and keeps the next id untouched
func (s *Connection) PeekNextStreamId() spdy.StreamId {
sid := s.nextStreamId
return sid
}
func (s *Connection) validateStreamId(rid spdy.StreamId) error {
if rid > 0x7fffffff || rid < s.receivedStreamId {
return ErrInvalidStreamId
}
s.receivedStreamId = rid + 2
return nil
}
func (s *Connection) addStream(stream *Stream) {
s.streamCond.L.Lock()
s.streams[stream.streamId] = stream
debugMessage("(%p) (%p) Stream added, broadcasting: %d", s, stream, stream.streamId)
s.streamCond.Broadcast()
s.streamCond.L.Unlock()
}
func (s *Connection) removeStream(stream *Stream) {
s.streamCond.L.Lock()
delete(s.streams, stream.streamId)
debugMessage("(%p) (%p) Stream removed, broadcasting: %d", s, stream, stream.streamId)
s.streamCond.Broadcast()
s.streamCond.L.Unlock()
}
func (s *Connection) getStream(streamId spdy.StreamId) (stream *Stream, ok bool) {
s.streamLock.RLock()
stream, ok = s.streams[streamId]
s.streamLock.RUnlock()
return
}
// FindStream looks up the given stream id and either waits for the
// stream to be found or returns nil if the stream id is no longer
// valid.
func (s *Connection) FindStream(streamId uint32) *Stream {
var stream *Stream
var ok bool
s.streamCond.L.Lock()
stream, ok = s.streams[spdy.StreamId(streamId)]
debugMessage("(%p) Found stream %d? %t", s, spdy.StreamId(streamId), ok)
for !ok && streamId >= uint32(s.receivedStreamId) {
s.streamCond.Wait()
stream, ok = s.streams[spdy.StreamId(streamId)]
}
s.streamCond.L.Unlock()
return stream
}
func (s *Connection) CloseChan() <-chan bool {
return s.closeChan
}

View File

@ -0,0 +1,38 @@
package spdystream
import (
"io"
"net/http"
)
// MirrorStreamHandler mirrors all streams.
func MirrorStreamHandler(stream *Stream) {
replyErr := stream.SendReply(http.Header{}, false)
if replyErr != nil {
return
}
go func() {
io.Copy(stream, stream)
stream.Close()
}()
go func() {
for {
header, receiveErr := stream.ReceiveHeader()
if receiveErr != nil {
return
}
sendErr := stream.SendHeader(header, false)
if sendErr != nil {
return
}
}
}()
}
// NoopStreamHandler does nothing when stream connects, most
// likely used with RejectAuthHandler which will not allow any
// streams to make it to the stream handler.
func NoOpStreamHandler(stream *Stream) {
stream.SendReply(http.Header{}, false)
}

View File

@ -0,0 +1,98 @@
package spdystream
import (
"container/heap"
"sync"
"github.com/docker/spdystream/spdy"
)
type prioritizedFrame struct {
frame spdy.Frame
priority uint8
insertId uint64
}
type frameQueue []*prioritizedFrame
func (fq frameQueue) Len() int {
return len(fq)
}
func (fq frameQueue) Less(i, j int) bool {
if fq[i].priority == fq[j].priority {
return fq[i].insertId < fq[j].insertId
}
return fq[i].priority < fq[j].priority
}
func (fq frameQueue) Swap(i, j int) {
fq[i], fq[j] = fq[j], fq[i]
}
func (fq *frameQueue) Push(x interface{}) {
*fq = append(*fq, x.(*prioritizedFrame))
}
func (fq *frameQueue) Pop() interface{} {
old := *fq
n := len(old)
*fq = old[0 : n-1]
return old[n-1]
}
type PriorityFrameQueue struct {
queue *frameQueue
c *sync.Cond
size int
nextInsertId uint64
drain bool
}
func NewPriorityFrameQueue(size int) *PriorityFrameQueue {
queue := make(frameQueue, 0, size)
heap.Init(&queue)
return &PriorityFrameQueue{
queue: &queue,
size: size,
c: sync.NewCond(&sync.Mutex{}),
}
}
func (q *PriorityFrameQueue) Push(frame spdy.Frame, priority uint8) {
q.c.L.Lock()
defer q.c.L.Unlock()
for q.queue.Len() >= q.size {
q.c.Wait()
}
pFrame := &prioritizedFrame{
frame: frame,
priority: priority,
insertId: q.nextInsertId,
}
q.nextInsertId = q.nextInsertId + 1
heap.Push(q.queue, pFrame)
q.c.Signal()
}
func (q *PriorityFrameQueue) Pop() spdy.Frame {
q.c.L.Lock()
defer q.c.L.Unlock()
for q.queue.Len() == 0 {
if q.drain {
return nil
}
q.c.Wait()
}
frame := heap.Pop(q.queue).(*prioritizedFrame).frame
q.c.Signal()
return frame
}
func (q *PriorityFrameQueue) Drain() {
q.c.L.Lock()
defer q.c.L.Unlock()
q.drain = true
q.c.Broadcast()
}

View File

@ -0,0 +1,187 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package spdy
// headerDictionary is the dictionary sent to the zlib compressor/decompressor.
var headerDictionary = []byte{
0x00, 0x00, 0x00, 0x07, 0x6f, 0x70, 0x74, 0x69,
0x6f, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x04, 0x68,
0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x70,
0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x03, 0x70,
0x75, 0x74, 0x00, 0x00, 0x00, 0x06, 0x64, 0x65,
0x6c, 0x65, 0x74, 0x65, 0x00, 0x00, 0x00, 0x05,
0x74, 0x72, 0x61, 0x63, 0x65, 0x00, 0x00, 0x00,
0x06, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x00,
0x00, 0x00, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x70,
0x74, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65,
0x74, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x63, 0x63,
0x65, 0x70, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f,
0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x0f,
0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x6c,
0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00,
0x00, 0x00, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70,
0x74, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73,
0x00, 0x00, 0x00, 0x03, 0x61, 0x67, 0x65, 0x00,
0x00, 0x00, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77,
0x00, 0x00, 0x00, 0x0d, 0x61, 0x75, 0x74, 0x68,
0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x00, 0x00, 0x00, 0x0d, 0x63, 0x61, 0x63,
0x68, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72,
0x6f, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x63, 0x6f,
0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x00, 0x00, 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74,
0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x73, 0x65,
0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, 0x6e, 0x74,
0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f,
0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10,
0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d,
0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65,
0x00, 0x00, 0x00, 0x0e, 0x63, 0x6f, 0x6e, 0x74,
0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x65, 0x6e, 0x67,
0x74, 0x68, 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f,
0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x6f,
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00,
0x00, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e,
0x74, 0x2d, 0x6d, 0x64, 0x35, 0x00, 0x00, 0x00,
0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,
0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00,
0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e,
0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00,
0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x00, 0x00,
0x00, 0x04, 0x65, 0x74, 0x61, 0x67, 0x00, 0x00,
0x00, 0x06, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74,
0x00, 0x00, 0x00, 0x07, 0x65, 0x78, 0x70, 0x69,
0x72, 0x65, 0x73, 0x00, 0x00, 0x00, 0x04, 0x66,
0x72, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x68,
0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x08, 0x69,
0x66, 0x2d, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00,
0x00, 0x00, 0x11, 0x69, 0x66, 0x2d, 0x6d, 0x6f,
0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2d, 0x73,
0x69, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x0d,
0x69, 0x66, 0x2d, 0x6e, 0x6f, 0x6e, 0x65, 0x2d,
0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x00, 0x00,
0x08, 0x69, 0x66, 0x2d, 0x72, 0x61, 0x6e, 0x67,
0x65, 0x00, 0x00, 0x00, 0x13, 0x69, 0x66, 0x2d,
0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69,
0x65, 0x64, 0x2d, 0x73, 0x69, 0x6e, 0x63, 0x65,
0x00, 0x00, 0x00, 0x0d, 0x6c, 0x61, 0x73, 0x74,
0x2d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65,
0x64, 0x00, 0x00, 0x00, 0x08, 0x6c, 0x6f, 0x63,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00,
0x0c, 0x6d, 0x61, 0x78, 0x2d, 0x66, 0x6f, 0x72,
0x77, 0x61, 0x72, 0x64, 0x73, 0x00, 0x00, 0x00,
0x06, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x00,
0x00, 0x00, 0x12, 0x70, 0x72, 0x6f, 0x78, 0x79,
0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74,
0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00,
0x13, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2d, 0x61,
0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x05,
0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, 0x00,
0x07, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72,
0x00, 0x00, 0x00, 0x0b, 0x72, 0x65, 0x74, 0x72,
0x79, 0x2d, 0x61, 0x66, 0x74, 0x65, 0x72, 0x00,
0x00, 0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65,
0x72, 0x00, 0x00, 0x00, 0x02, 0x74, 0x65, 0x00,
0x00, 0x00, 0x07, 0x74, 0x72, 0x61, 0x69, 0x6c,
0x65, 0x72, 0x00, 0x00, 0x00, 0x11, 0x74, 0x72,
0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x65,
0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00,
0x00, 0x00, 0x07, 0x75, 0x70, 0x67, 0x72, 0x61,
0x64, 0x65, 0x00, 0x00, 0x00, 0x0a, 0x75, 0x73,
0x65, 0x72, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74,
0x00, 0x00, 0x00, 0x04, 0x76, 0x61, 0x72, 0x79,
0x00, 0x00, 0x00, 0x03, 0x76, 0x69, 0x61, 0x00,
0x00, 0x00, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69,
0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, 0x77, 0x77,
0x77, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e,
0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00,
0x00, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64,
0x00, 0x00, 0x00, 0x03, 0x67, 0x65, 0x74, 0x00,
0x00, 0x00, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75,
0x73, 0x00, 0x00, 0x00, 0x06, 0x32, 0x30, 0x30,
0x20, 0x4f, 0x4b, 0x00, 0x00, 0x00, 0x07, 0x76,
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00,
0x00, 0x08, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31,
0x2e, 0x31, 0x00, 0x00, 0x00, 0x03, 0x75, 0x72,
0x6c, 0x00, 0x00, 0x00, 0x06, 0x70, 0x75, 0x62,
0x6c, 0x69, 0x63, 0x00, 0x00, 0x00, 0x0a, 0x73,
0x65, 0x74, 0x2d, 0x63, 0x6f, 0x6f, 0x6b, 0x69,
0x65, 0x00, 0x00, 0x00, 0x0a, 0x6b, 0x65, 0x65,
0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x00,
0x00, 0x00, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69,
0x6e, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x32,
0x30, 0x31, 0x32, 0x30, 0x32, 0x32, 0x30, 0x35,
0x32, 0x30, 0x36, 0x33, 0x30, 0x30, 0x33, 0x30,
0x32, 0x33, 0x30, 0x33, 0x33, 0x30, 0x34, 0x33,
0x30, 0x35, 0x33, 0x30, 0x36, 0x33, 0x30, 0x37,
0x34, 0x30, 0x32, 0x34, 0x30, 0x35, 0x34, 0x30,
0x36, 0x34, 0x30, 0x37, 0x34, 0x30, 0x38, 0x34,
0x30, 0x39, 0x34, 0x31, 0x30, 0x34, 0x31, 0x31,
0x34, 0x31, 0x32, 0x34, 0x31, 0x33, 0x34, 0x31,
0x34, 0x34, 0x31, 0x35, 0x34, 0x31, 0x36, 0x34,
0x31, 0x37, 0x35, 0x30, 0x32, 0x35, 0x30, 0x34,
0x35, 0x30, 0x35, 0x32, 0x30, 0x33, 0x20, 0x4e,
0x6f, 0x6e, 0x2d, 0x41, 0x75, 0x74, 0x68, 0x6f,
0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65,
0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x32, 0x30, 0x34, 0x20,
0x4e, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65,
0x6e, 0x74, 0x33, 0x30, 0x31, 0x20, 0x4d, 0x6f,
0x76, 0x65, 0x64, 0x20, 0x50, 0x65, 0x72, 0x6d,
0x61, 0x6e, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x34,
0x30, 0x30, 0x20, 0x42, 0x61, 0x64, 0x20, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x34, 0x30,
0x31, 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68,
0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x34, 0x30,
0x33, 0x20, 0x46, 0x6f, 0x72, 0x62, 0x69, 0x64,
0x64, 0x65, 0x6e, 0x34, 0x30, 0x34, 0x20, 0x4e,
0x6f, 0x74, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64,
0x35, 0x30, 0x30, 0x20, 0x49, 0x6e, 0x74, 0x65,
0x72, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72,
0x76, 0x65, 0x72, 0x20, 0x45, 0x72, 0x72, 0x6f,
0x72, 0x35, 0x30, 0x31, 0x20, 0x4e, 0x6f, 0x74,
0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65,
0x6e, 0x74, 0x65, 0x64, 0x35, 0x30, 0x33, 0x20,
0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20,
0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61,
0x62, 0x6c, 0x65, 0x4a, 0x61, 0x6e, 0x20, 0x46,
0x65, 0x62, 0x20, 0x4d, 0x61, 0x72, 0x20, 0x41,
0x70, 0x72, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x4a,
0x75, 0x6e, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x41,
0x75, 0x67, 0x20, 0x53, 0x65, 0x70, 0x74, 0x20,
0x4f, 0x63, 0x74, 0x20, 0x4e, 0x6f, 0x76, 0x20,
0x44, 0x65, 0x63, 0x20, 0x30, 0x30, 0x3a, 0x30,
0x30, 0x3a, 0x30, 0x30, 0x20, 0x4d, 0x6f, 0x6e,
0x2c, 0x20, 0x54, 0x75, 0x65, 0x2c, 0x20, 0x57,
0x65, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x75, 0x2c,
0x20, 0x46, 0x72, 0x69, 0x2c, 0x20, 0x53, 0x61,
0x74, 0x2c, 0x20, 0x53, 0x75, 0x6e, 0x2c, 0x20,
0x47, 0x4d, 0x54, 0x63, 0x68, 0x75, 0x6e, 0x6b,
0x65, 0x64, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f,
0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x69, 0x6d, 0x61,
0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0x2c, 0x69,
0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x67,
0x2c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67,
0x69, 0x66, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69,
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78,
0x6d, 0x6c, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69,
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78,
0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c,
0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c,
0x61, 0x69, 0x6e, 0x2c, 0x74, 0x65, 0x78, 0x74,
0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72,
0x69, 0x70, 0x74, 0x2c, 0x70, 0x75, 0x62, 0x6c,
0x69, 0x63, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74,
0x65, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65,
0x3d, 0x67, 0x7a, 0x69, 0x70, 0x2c, 0x64, 0x65,
0x66, 0x6c, 0x61, 0x74, 0x65, 0x2c, 0x73, 0x64,
0x63, 0x68, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65,
0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x63,
0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69,
0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d,
0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a,
0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e,
}

View File

@ -0,0 +1,348 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package spdy
import (
"compress/zlib"
"encoding/binary"
"io"
"net/http"
"strings"
)
func (frame *SynStreamFrame) read(h ControlFrameHeader, f *Framer) error {
return f.readSynStreamFrame(h, frame)
}
func (frame *SynReplyFrame) read(h ControlFrameHeader, f *Framer) error {
return f.readSynReplyFrame(h, frame)
}
func (frame *RstStreamFrame) read(h ControlFrameHeader, f *Framer) error {
frame.CFHeader = h
if err := binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
return err
}
if err := binary.Read(f.r, binary.BigEndian, &frame.Status); err != nil {
return err
}
if frame.Status == 0 {
return &Error{InvalidControlFrame, frame.StreamId}
}
if frame.StreamId == 0 {
return &Error{ZeroStreamId, 0}
}
return nil
}
func (frame *SettingsFrame) read(h ControlFrameHeader, f *Framer) error {
frame.CFHeader = h
var numSettings uint32
if err := binary.Read(f.r, binary.BigEndian, &numSettings); err != nil {
return err
}
frame.FlagIdValues = make([]SettingsFlagIdValue, numSettings)
for i := uint32(0); i < numSettings; i++ {
if err := binary.Read(f.r, binary.BigEndian, &frame.FlagIdValues[i].Id); err != nil {
return err
}
frame.FlagIdValues[i].Flag = SettingsFlag((frame.FlagIdValues[i].Id & 0xff000000) >> 24)
frame.FlagIdValues[i].Id &= 0xffffff
if err := binary.Read(f.r, binary.BigEndian, &frame.FlagIdValues[i].Value); err != nil {
return err
}
}
return nil
}
func (frame *PingFrame) read(h ControlFrameHeader, f *Framer) error {
frame.CFHeader = h
if err := binary.Read(f.r, binary.BigEndian, &frame.Id); err != nil {
return err
}
if frame.Id == 0 {
return &Error{ZeroStreamId, 0}
}
if frame.CFHeader.Flags != 0 {
return &Error{InvalidControlFrame, StreamId(frame.Id)}
}
return nil
}
func (frame *GoAwayFrame) read(h ControlFrameHeader, f *Framer) error {
frame.CFHeader = h
if err := binary.Read(f.r, binary.BigEndian, &frame.LastGoodStreamId); err != nil {
return err
}
if frame.CFHeader.Flags != 0 {
return &Error{InvalidControlFrame, frame.LastGoodStreamId}
}
if frame.CFHeader.length != 8 {
return &Error{InvalidControlFrame, frame.LastGoodStreamId}
}
if err := binary.Read(f.r, binary.BigEndian, &frame.Status); err != nil {
return err
}
return nil
}
func (frame *HeadersFrame) read(h ControlFrameHeader, f *Framer) error {
return f.readHeadersFrame(h, frame)
}
func (frame *WindowUpdateFrame) read(h ControlFrameHeader, f *Framer) error {
frame.CFHeader = h
if err := binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
return err
}
if frame.CFHeader.Flags != 0 {
return &Error{InvalidControlFrame, frame.StreamId}
}
if frame.CFHeader.length != 8 {
return &Error{InvalidControlFrame, frame.StreamId}
}
if err := binary.Read(f.r, binary.BigEndian, &frame.DeltaWindowSize); err != nil {
return err
}
return nil
}
func newControlFrame(frameType ControlFrameType) (controlFrame, error) {
ctor, ok := cframeCtor[frameType]
if !ok {
return nil, &Error{Err: InvalidControlFrame}
}
return ctor(), nil
}
var cframeCtor = map[ControlFrameType]func() controlFrame{
TypeSynStream: func() controlFrame { return new(SynStreamFrame) },
TypeSynReply: func() controlFrame { return new(SynReplyFrame) },
TypeRstStream: func() controlFrame { return new(RstStreamFrame) },
TypeSettings: func() controlFrame { return new(SettingsFrame) },
TypePing: func() controlFrame { return new(PingFrame) },
TypeGoAway: func() controlFrame { return new(GoAwayFrame) },
TypeHeaders: func() controlFrame { return new(HeadersFrame) },
TypeWindowUpdate: func() controlFrame { return new(WindowUpdateFrame) },
}
func (f *Framer) uncorkHeaderDecompressor(payloadSize int64) error {
if f.headerDecompressor != nil {
f.headerReader.N = payloadSize
return nil
}
f.headerReader = io.LimitedReader{R: f.r, N: payloadSize}
decompressor, err := zlib.NewReaderDict(&f.headerReader, []byte(headerDictionary))
if err != nil {
return err
}
f.headerDecompressor = decompressor
return nil
}
// ReadFrame reads SPDY encoded data and returns a decompressed Frame.
func (f *Framer) ReadFrame() (Frame, error) {
var firstWord uint32
if err := binary.Read(f.r, binary.BigEndian, &firstWord); err != nil {
return nil, err
}
if firstWord&0x80000000 != 0 {
frameType := ControlFrameType(firstWord & 0xffff)
version := uint16(firstWord >> 16 & 0x7fff)
return f.parseControlFrame(version, frameType)
}
return f.parseDataFrame(StreamId(firstWord & 0x7fffffff))
}
func (f *Framer) parseControlFrame(version uint16, frameType ControlFrameType) (Frame, error) {
var length uint32
if err := binary.Read(f.r, binary.BigEndian, &length); err != nil {
return nil, err
}
flags := ControlFlags((length & 0xff000000) >> 24)
length &= 0xffffff
header := ControlFrameHeader{version, frameType, flags, length}
cframe, err := newControlFrame(frameType)
if err != nil {
return nil, err
}
if err = cframe.read(header, f); err != nil {
return nil, err
}
return cframe, nil
}
func parseHeaderValueBlock(r io.Reader, streamId StreamId) (http.Header, error) {
var numHeaders uint32
if err := binary.Read(r, binary.BigEndian, &numHeaders); err != nil {
return nil, err
}
var e error
h := make(http.Header, int(numHeaders))
for i := 0; i < int(numHeaders); i++ {
var length uint32
if err := binary.Read(r, binary.BigEndian, &length); err != nil {
return nil, err
}
nameBytes := make([]byte, length)
if _, err := io.ReadFull(r, nameBytes); err != nil {
return nil, err
}
name := string(nameBytes)
if name != strings.ToLower(name) {
e = &Error{UnlowercasedHeaderName, streamId}
name = strings.ToLower(name)
}
if h[name] != nil {
e = &Error{DuplicateHeaders, streamId}
}
if err := binary.Read(r, binary.BigEndian, &length); err != nil {
return nil, err
}
value := make([]byte, length)
if _, err := io.ReadFull(r, value); err != nil {
return nil, err
}
valueList := strings.Split(string(value), headerValueSeparator)
for _, v := range valueList {
h.Add(name, v)
}
}
if e != nil {
return h, e
}
return h, nil
}
func (f *Framer) readSynStreamFrame(h ControlFrameHeader, frame *SynStreamFrame) error {
frame.CFHeader = h
var err error
if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
return err
}
if err = binary.Read(f.r, binary.BigEndian, &frame.AssociatedToStreamId); err != nil {
return err
}
if err = binary.Read(f.r, binary.BigEndian, &frame.Priority); err != nil {
return err
}
frame.Priority >>= 5
if err = binary.Read(f.r, binary.BigEndian, &frame.Slot); err != nil {
return err
}
reader := f.r
if !f.headerCompressionDisabled {
err := f.uncorkHeaderDecompressor(int64(h.length - 10))
if err != nil {
return err
}
reader = f.headerDecompressor
}
frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
if !f.headerCompressionDisabled && (err == io.EOF && f.headerReader.N == 0 || f.headerReader.N != 0) {
err = &Error{WrongCompressedPayloadSize, 0}
}
if err != nil {
return err
}
for h := range frame.Headers {
if invalidReqHeaders[h] {
return &Error{InvalidHeaderPresent, frame.StreamId}
}
}
if frame.StreamId == 0 {
return &Error{ZeroStreamId, 0}
}
return nil
}
func (f *Framer) readSynReplyFrame(h ControlFrameHeader, frame *SynReplyFrame) error {
frame.CFHeader = h
var err error
if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
return err
}
reader := f.r
if !f.headerCompressionDisabled {
err := f.uncorkHeaderDecompressor(int64(h.length - 4))
if err != nil {
return err
}
reader = f.headerDecompressor
}
frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
if !f.headerCompressionDisabled && (err == io.EOF && f.headerReader.N == 0 || f.headerReader.N != 0) {
err = &Error{WrongCompressedPayloadSize, 0}
}
if err != nil {
return err
}
for h := range frame.Headers {
if invalidRespHeaders[h] {
return &Error{InvalidHeaderPresent, frame.StreamId}
}
}
if frame.StreamId == 0 {
return &Error{ZeroStreamId, 0}
}
return nil
}
func (f *Framer) readHeadersFrame(h ControlFrameHeader, frame *HeadersFrame) error {
frame.CFHeader = h
var err error
if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
return err
}
reader := f.r
if !f.headerCompressionDisabled {
err := f.uncorkHeaderDecompressor(int64(h.length - 4))
if err != nil {
return err
}
reader = f.headerDecompressor
}
frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
if !f.headerCompressionDisabled && (err == io.EOF && f.headerReader.N == 0 || f.headerReader.N != 0) {
err = &Error{WrongCompressedPayloadSize, 0}
}
if err != nil {
return err
}
var invalidHeaders map[string]bool
if frame.StreamId%2 == 0 {
invalidHeaders = invalidReqHeaders
} else {
invalidHeaders = invalidRespHeaders
}
for h := range frame.Headers {
if invalidHeaders[h] {
return &Error{InvalidHeaderPresent, frame.StreamId}
}
}
if frame.StreamId == 0 {
return &Error{ZeroStreamId, 0}
}
return nil
}
func (f *Framer) parseDataFrame(streamId StreamId) (*DataFrame, error) {
var length uint32
if err := binary.Read(f.r, binary.BigEndian, &length); err != nil {
return nil, err
}
var frame DataFrame
frame.StreamId = streamId
frame.Flags = DataFlags(length >> 24)
length &= 0xffffff
frame.Data = make([]byte, length)
if _, err := io.ReadFull(f.r, frame.Data); err != nil {
return nil, err
}
if frame.StreamId == 0 {
return nil, &Error{ZeroStreamId, 0}
}
return &frame, nil
}

View File

@ -0,0 +1,275 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package spdy implements the SPDY protocol (currently SPDY/3), described in
// http://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3.
package spdy
import (
"bytes"
"compress/zlib"
"io"
"net/http"
)
// Version is the protocol version number that this package implements.
const Version = 3
// ControlFrameType stores the type field in a control frame header.
type ControlFrameType uint16
const (
TypeSynStream ControlFrameType = 0x0001
TypeSynReply = 0x0002
TypeRstStream = 0x0003
TypeSettings = 0x0004
TypePing = 0x0006
TypeGoAway = 0x0007
TypeHeaders = 0x0008
TypeWindowUpdate = 0x0009
)
// ControlFlags are the flags that can be set on a control frame.
type ControlFlags uint8
const (
ControlFlagFin ControlFlags = 0x01
ControlFlagUnidirectional = 0x02
ControlFlagSettingsClearSettings = 0x01
)
// DataFlags are the flags that can be set on a data frame.
type DataFlags uint8
const (
DataFlagFin DataFlags = 0x01
)
// MaxDataLength is the maximum number of bytes that can be stored in one frame.
const MaxDataLength = 1<<24 - 1
// headerValueSepator separates multiple header values.
const headerValueSeparator = "\x00"
// Frame is a single SPDY frame in its unpacked in-memory representation. Use
// Framer to read and write it.
type Frame interface {
write(f *Framer) error
}
// ControlFrameHeader contains all the fields in a control frame header,
// in its unpacked in-memory representation.
type ControlFrameHeader struct {
// Note, high bit is the "Control" bit.
version uint16 // spdy version number
frameType ControlFrameType
Flags ControlFlags
length uint32 // length of data field
}
type controlFrame interface {
Frame
read(h ControlFrameHeader, f *Framer) error
}
// StreamId represents a 31-bit value identifying the stream.
type StreamId uint32
// SynStreamFrame is the unpacked, in-memory representation of a SYN_STREAM
// frame.
type SynStreamFrame struct {
CFHeader ControlFrameHeader
StreamId StreamId
AssociatedToStreamId StreamId // stream id for a stream which this stream is associated to
Priority uint8 // priority of this frame (3-bit)
Slot uint8 // index in the server's credential vector of the client certificate
Headers http.Header
}
// SynReplyFrame is the unpacked, in-memory representation of a SYN_REPLY frame.
type SynReplyFrame struct {
CFHeader ControlFrameHeader
StreamId StreamId
Headers http.Header
}
// RstStreamStatus represents the status that led to a RST_STREAM.
type RstStreamStatus uint32
const (
ProtocolError RstStreamStatus = iota + 1
InvalidStream
RefusedStream
UnsupportedVersion
Cancel
InternalError
FlowControlError
StreamInUse
StreamAlreadyClosed
InvalidCredentials
FrameTooLarge
)
// RstStreamFrame is the unpacked, in-memory representation of a RST_STREAM
// frame.
type RstStreamFrame struct {
CFHeader ControlFrameHeader
StreamId StreamId
Status RstStreamStatus
}
// SettingsFlag represents a flag in a SETTINGS frame.
type SettingsFlag uint8
const (
FlagSettingsPersistValue SettingsFlag = 0x1
FlagSettingsPersisted = 0x2
)
// SettingsFlag represents the id of an id/value pair in a SETTINGS frame.
type SettingsId uint32
const (
SettingsUploadBandwidth SettingsId = iota + 1
SettingsDownloadBandwidth
SettingsRoundTripTime
SettingsMaxConcurrentStreams
SettingsCurrentCwnd
SettingsDownloadRetransRate
SettingsInitialWindowSize
SettingsClientCretificateVectorSize
)
// SettingsFlagIdValue is the unpacked, in-memory representation of the
// combined flag/id/value for a setting in a SETTINGS frame.
type SettingsFlagIdValue struct {
Flag SettingsFlag
Id SettingsId
Value uint32
}
// SettingsFrame is the unpacked, in-memory representation of a SPDY
// SETTINGS frame.
type SettingsFrame struct {
CFHeader ControlFrameHeader
FlagIdValues []SettingsFlagIdValue
}
// PingFrame is the unpacked, in-memory representation of a PING frame.
type PingFrame struct {
CFHeader ControlFrameHeader
Id uint32 // unique id for this ping, from server is even, from client is odd.
}
// GoAwayStatus represents the status in a GoAwayFrame.
type GoAwayStatus uint32
const (
GoAwayOK GoAwayStatus = iota
GoAwayProtocolError
GoAwayInternalError
)
// GoAwayFrame is the unpacked, in-memory representation of a GOAWAY frame.
type GoAwayFrame struct {
CFHeader ControlFrameHeader
LastGoodStreamId StreamId // last stream id which was accepted by sender
Status GoAwayStatus
}
// HeadersFrame is the unpacked, in-memory representation of a HEADERS frame.
type HeadersFrame struct {
CFHeader ControlFrameHeader
StreamId StreamId
Headers http.Header
}
// WindowUpdateFrame is the unpacked, in-memory representation of a
// WINDOW_UPDATE frame.
type WindowUpdateFrame struct {
CFHeader ControlFrameHeader
StreamId StreamId
DeltaWindowSize uint32 // additional number of bytes to existing window size
}
// TODO: Implement credential frame and related methods.
// DataFrame is the unpacked, in-memory representation of a DATA frame.
type DataFrame struct {
// Note, high bit is the "Control" bit. Should be 0 for data frames.
StreamId StreamId
Flags DataFlags
Data []byte // payload data of this frame
}
// A SPDY specific error.
type ErrorCode string
const (
UnlowercasedHeaderName ErrorCode = "header was not lowercased"
DuplicateHeaders = "multiple headers with same name"
WrongCompressedPayloadSize = "compressed payload size was incorrect"
UnknownFrameType = "unknown frame type"
InvalidControlFrame = "invalid control frame"
InvalidDataFrame = "invalid data frame"
InvalidHeaderPresent = "frame contained invalid header"
ZeroStreamId = "stream id zero is disallowed"
)
// Error contains both the type of error and additional values. StreamId is 0
// if Error is not associated with a stream.
type Error struct {
Err ErrorCode
StreamId StreamId
}
func (e *Error) Error() string {
return string(e.Err)
}
var invalidReqHeaders = map[string]bool{
"Connection": true,
"Host": true,
"Keep-Alive": true,
"Proxy-Connection": true,
"Transfer-Encoding": true,
}
var invalidRespHeaders = map[string]bool{
"Connection": true,
"Keep-Alive": true,
"Proxy-Connection": true,
"Transfer-Encoding": true,
}
// Framer handles serializing/deserializing SPDY frames, including compressing/
// decompressing payloads.
type Framer struct {
headerCompressionDisabled bool
w io.Writer
headerBuf *bytes.Buffer
headerCompressor *zlib.Writer
r io.Reader
headerReader io.LimitedReader
headerDecompressor io.ReadCloser
}
// NewFramer allocates a new Framer for a given SPDY connection, represented by
// a io.Writer and io.Reader. Note that Framer will read and write individual fields
// from/to the Reader and Writer, so the caller should pass in an appropriately
// buffered implementation to optimize performance.
func NewFramer(w io.Writer, r io.Reader) (*Framer, error) {
compressBuf := new(bytes.Buffer)
compressor, err := zlib.NewWriterLevelDict(compressBuf, zlib.BestCompression, []byte(headerDictionary))
if err != nil {
return nil, err
}
framer := &Framer{
w: w,
headerBuf: compressBuf,
headerCompressor: compressor,
r: r,
}
return framer, nil
}

View File

@ -0,0 +1,318 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package spdy
import (
"encoding/binary"
"io"
"net/http"
"strings"
)
func (frame *SynStreamFrame) write(f *Framer) error {
return f.writeSynStreamFrame(frame)
}
func (frame *SynReplyFrame) write(f *Framer) error {
return f.writeSynReplyFrame(frame)
}
func (frame *RstStreamFrame) write(f *Framer) (err error) {
if frame.StreamId == 0 {
return &Error{ZeroStreamId, 0}
}
frame.CFHeader.version = Version
frame.CFHeader.frameType = TypeRstStream
frame.CFHeader.Flags = 0
frame.CFHeader.length = 8
// Serialize frame to Writer.
if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
return
}
if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
return
}
if frame.Status == 0 {
return &Error{InvalidControlFrame, frame.StreamId}
}
if err = binary.Write(f.w, binary.BigEndian, frame.Status); err != nil {
return
}
return
}
func (frame *SettingsFrame) write(f *Framer) (err error) {
frame.CFHeader.version = Version
frame.CFHeader.frameType = TypeSettings
frame.CFHeader.length = uint32(len(frame.FlagIdValues)*8 + 4)
// Serialize frame to Writer.
if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
return
}
if err = binary.Write(f.w, binary.BigEndian, uint32(len(frame.FlagIdValues))); err != nil {
return
}
for _, flagIdValue := range frame.FlagIdValues {
flagId := uint32(flagIdValue.Flag)<<24 | uint32(flagIdValue.Id)
if err = binary.Write(f.w, binary.BigEndian, flagId); err != nil {
return
}
if err = binary.Write(f.w, binary.BigEndian, flagIdValue.Value); err != nil {
return
}
}
return
}
func (frame *PingFrame) write(f *Framer) (err error) {
if frame.Id == 0 {
return &Error{ZeroStreamId, 0}
}
frame.CFHeader.version = Version
frame.CFHeader.frameType = TypePing
frame.CFHeader.Flags = 0
frame.CFHeader.length = 4
// Serialize frame to Writer.
if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
return
}
if err = binary.Write(f.w, binary.BigEndian, frame.Id); err != nil {
return
}
return
}
func (frame *GoAwayFrame) write(f *Framer) (err error) {
frame.CFHeader.version = Version
frame.CFHeader.frameType = TypeGoAway
frame.CFHeader.Flags = 0
frame.CFHeader.length = 8
// Serialize frame to Writer.
if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
return
}
if err = binary.Write(f.w, binary.BigEndian, frame.LastGoodStreamId); err != nil {
return
}
if err = binary.Write(f.w, binary.BigEndian, frame.Status); err != nil {
return
}
return nil
}
func (frame *HeadersFrame) write(f *Framer) error {
return f.writeHeadersFrame(frame)
}
func (frame *WindowUpdateFrame) write(f *Framer) (err error) {
frame.CFHeader.version = Version
frame.CFHeader.frameType = TypeWindowUpdate
frame.CFHeader.Flags = 0
frame.CFHeader.length = 8
// Serialize frame to Writer.
if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
return
}
if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
return
}
if err = binary.Write(f.w, binary.BigEndian, frame.DeltaWindowSize); err != nil {
return
}
return nil
}
func (frame *DataFrame) write(f *Framer) error {
return f.writeDataFrame(frame)
}
// WriteFrame writes a frame.
func (f *Framer) WriteFrame(frame Frame) error {
return frame.write(f)
}
func writeControlFrameHeader(w io.Writer, h ControlFrameHeader) error {
if err := binary.Write(w, binary.BigEndian, 0x8000|h.version); err != nil {
return err
}
if err := binary.Write(w, binary.BigEndian, h.frameType); err != nil {
return err
}
flagsAndLength := uint32(h.Flags)<<24 | h.length
if err := binary.Write(w, binary.BigEndian, flagsAndLength); err != nil {
return err
}
return nil
}
func writeHeaderValueBlock(w io.Writer, h http.Header) (n int, err error) {
n = 0
if err = binary.Write(w, binary.BigEndian, uint32(len(h))); err != nil {
return
}
n += 2
for name, values := range h {
if err = binary.Write(w, binary.BigEndian, uint32(len(name))); err != nil {
return
}
n += 2
name = strings.ToLower(name)
if _, err = io.WriteString(w, name); err != nil {
return
}
n += len(name)
v := strings.Join(values, headerValueSeparator)
if err = binary.Write(w, binary.BigEndian, uint32(len(v))); err != nil {
return
}
n += 2
if _, err = io.WriteString(w, v); err != nil {
return
}
n += len(v)
}
return
}
func (f *Framer) writeSynStreamFrame(frame *SynStreamFrame) (err error) {
if frame.StreamId == 0 {
return &Error{ZeroStreamId, 0}
}
// Marshal the headers.
var writer io.Writer = f.headerBuf
if !f.headerCompressionDisabled {
writer = f.headerCompressor
}
if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil {
return
}
if !f.headerCompressionDisabled {
f.headerCompressor.Flush()
}
// Set ControlFrameHeader.
frame.CFHeader.version = Version
frame.CFHeader.frameType = TypeSynStream
frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 10)
// Serialize frame to Writer.
if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
return err
}
if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
return err
}
if err = binary.Write(f.w, binary.BigEndian, frame.AssociatedToStreamId); err != nil {
return err
}
if err = binary.Write(f.w, binary.BigEndian, frame.Priority<<5); err != nil {
return err
}
if err = binary.Write(f.w, binary.BigEndian, frame.Slot); err != nil {
return err
}
if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil {
return err
}
f.headerBuf.Reset()
return nil
}
func (f *Framer) writeSynReplyFrame(frame *SynReplyFrame) (err error) {
if frame.StreamId == 0 {
return &Error{ZeroStreamId, 0}
}
// Marshal the headers.
var writer io.Writer = f.headerBuf
if !f.headerCompressionDisabled {
writer = f.headerCompressor
}
if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil {
return
}
if !f.headerCompressionDisabled {
f.headerCompressor.Flush()
}
// Set ControlFrameHeader.
frame.CFHeader.version = Version
frame.CFHeader.frameType = TypeSynReply
frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 4)
// Serialize frame to Writer.
if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
return
}
if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
return
}
if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil {
return
}
f.headerBuf.Reset()
return
}
func (f *Framer) writeHeadersFrame(frame *HeadersFrame) (err error) {
if frame.StreamId == 0 {
return &Error{ZeroStreamId, 0}
}
// Marshal the headers.
var writer io.Writer = f.headerBuf
if !f.headerCompressionDisabled {
writer = f.headerCompressor
}
if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil {
return
}
if !f.headerCompressionDisabled {
f.headerCompressor.Flush()
}
// Set ControlFrameHeader.
frame.CFHeader.version = Version
frame.CFHeader.frameType = TypeHeaders
frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 4)
// Serialize frame to Writer.
if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
return
}
if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
return
}
if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil {
return
}
f.headerBuf.Reset()
return
}
func (f *Framer) writeDataFrame(frame *DataFrame) (err error) {
if frame.StreamId == 0 {
return &Error{ZeroStreamId, 0}
}
if frame.StreamId&0x80000000 != 0 || len(frame.Data) > MaxDataLength {
return &Error{InvalidDataFrame, frame.StreamId}
}
// Serialize frame to Writer.
if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
return
}
flagsAndLength := uint32(frame.Flags)<<24 | uint32(len(frame.Data))
if err = binary.Write(f.w, binary.BigEndian, flagsAndLength); err != nil {
return
}
if _, err = f.w.Write(frame.Data); err != nil {
return
}
return nil
}

View File

@ -0,0 +1,327 @@
package spdystream
import (
"errors"
"fmt"
"io"
"net"
"net/http"
"sync"
"time"
"github.com/docker/spdystream/spdy"
)
var (
ErrUnreadPartialData = errors.New("unread partial data")
)
type Stream struct {
streamId spdy.StreamId
parent *Stream
conn *Connection
startChan chan error
dataLock sync.RWMutex
dataChan chan []byte
unread []byte
priority uint8
headers http.Header
headerChan chan http.Header
finishLock sync.Mutex
finished bool
replyCond *sync.Cond
replied bool
closeLock sync.Mutex
closeChan chan bool
}
// WriteData writes data to stream, sending a dataframe per call
func (s *Stream) WriteData(data []byte, fin bool) error {
s.waitWriteReply()
var flags spdy.DataFlags
if fin {
flags = spdy.DataFlagFin
s.finishLock.Lock()
if s.finished {
s.finishLock.Unlock()
return ErrWriteClosedStream
}
s.finished = true
s.finishLock.Unlock()
}
dataFrame := &spdy.DataFrame{
StreamId: s.streamId,
Flags: flags,
Data: data,
}
debugMessage("(%p) (%d) Writing data frame", s, s.streamId)
return s.conn.framer.WriteFrame(dataFrame)
}
// Write writes bytes to a stream, calling write data for each call.
func (s *Stream) Write(data []byte) (n int, err error) {
err = s.WriteData(data, false)
if err == nil {
n = len(data)
}
return
}
// Read reads bytes from a stream, a single read will never get more
// than what is sent on a single data frame, but a multiple calls to
// read may get data from the same data frame.
func (s *Stream) Read(p []byte) (n int, err error) {
if s.unread == nil {
select {
case <-s.closeChan:
return 0, io.EOF
case read, ok := <-s.dataChan:
if !ok {
return 0, io.EOF
}
s.unread = read
}
}
n = copy(p, s.unread)
if n < len(s.unread) {
s.unread = s.unread[n:]
} else {
s.unread = nil
}
return
}
// ReadData reads an entire data frame and returns the byte array
// from the data frame. If there is unread data from the result
// of a Read call, this function will return an ErrUnreadPartialData.
func (s *Stream) ReadData() ([]byte, error) {
debugMessage("(%p) Reading data from %d", s, s.streamId)
if s.unread != nil {
return nil, ErrUnreadPartialData
}
select {
case <-s.closeChan:
return nil, io.EOF
case read, ok := <-s.dataChan:
if !ok {
return nil, io.EOF
}
return read, nil
}
}
func (s *Stream) waitWriteReply() {
if s.replyCond != nil {
s.replyCond.L.Lock()
for !s.replied {
s.replyCond.Wait()
}
s.replyCond.L.Unlock()
}
}
// Wait waits for the stream to receive a reply.
func (s *Stream) Wait() error {
return s.WaitTimeout(time.Duration(0))
}
// WaitTimeout waits for the stream to receive a reply or for timeout.
// When the timeout is reached, ErrTimeout will be returned.
func (s *Stream) WaitTimeout(timeout time.Duration) error {
var timeoutChan <-chan time.Time
if timeout > time.Duration(0) {
timeoutChan = time.After(timeout)
}
select {
case err := <-s.startChan:
if err != nil {
return err
}
break
case <-timeoutChan:
return ErrTimeout
}
return nil
}
// Close closes the stream by sending an empty data frame with the
// finish flag set, indicating this side is finished with the stream.
func (s *Stream) Close() error {
select {
case <-s.closeChan:
// Stream is now fully closed
s.conn.removeStream(s)
default:
break
}
return s.WriteData([]byte{}, true)
}
// Reset sends a reset frame, putting the stream into the fully closed state.
func (s *Stream) Reset() error {
s.conn.removeStream(s)
return s.resetStream()
}
func (s *Stream) resetStream() error {
// Always call closeRemoteChannels, even if s.finished is already true.
// This makes it so that stream.Close() followed by stream.Reset() allows
// stream.Read() to unblock.
s.closeRemoteChannels()
s.finishLock.Lock()
if s.finished {
s.finishLock.Unlock()
return nil
}
s.finished = true
s.finishLock.Unlock()
resetFrame := &spdy.RstStreamFrame{
StreamId: s.streamId,
Status: spdy.Cancel,
}
return s.conn.framer.WriteFrame(resetFrame)
}
// CreateSubStream creates a stream using the current as the parent
func (s *Stream) CreateSubStream(headers http.Header, fin bool) (*Stream, error) {
return s.conn.CreateStream(headers, s, fin)
}
// SetPriority sets the stream priority, does not affect the
// remote priority of this stream after Open has been called.
// Valid values are 0 through 7, 0 being the highest priority
// and 7 the lowest.
func (s *Stream) SetPriority(priority uint8) {
s.priority = priority
}
// SendHeader sends a header frame across the stream
func (s *Stream) SendHeader(headers http.Header, fin bool) error {
return s.conn.sendHeaders(headers, s, fin)
}
// SendReply sends a reply on a stream, only valid to be called once
// when handling a new stream
func (s *Stream) SendReply(headers http.Header, fin bool) error {
if s.replyCond == nil {
return errors.New("cannot reply on initiated stream")
}
s.replyCond.L.Lock()
defer s.replyCond.L.Unlock()
if s.replied {
return nil
}
err := s.conn.sendReply(headers, s, fin)
if err != nil {
return err
}
s.replied = true
s.replyCond.Broadcast()
return nil
}
// Refuse sends a reset frame with the status refuse, only
// valid to be called once when handling a new stream. This
// may be used to indicate that a stream is not allowed
// when http status codes are not being used.
func (s *Stream) Refuse() error {
if s.replied {
return nil
}
s.replied = true
return s.conn.sendReset(spdy.RefusedStream, s)
}
// Cancel sends a reset frame with the status canceled. This
// can be used at any time by the creator of the Stream to
// indicate the stream is no longer needed.
func (s *Stream) Cancel() error {
return s.conn.sendReset(spdy.Cancel, s)
}
// ReceiveHeader receives a header sent on the other side
// of the stream. This function will block until a header
// is received or stream is closed.
func (s *Stream) ReceiveHeader() (http.Header, error) {
select {
case <-s.closeChan:
break
case header, ok := <-s.headerChan:
if !ok {
return nil, fmt.Errorf("header chan closed")
}
return header, nil
}
return nil, fmt.Errorf("stream closed")
}
// Parent returns the parent stream
func (s *Stream) Parent() *Stream {
return s.parent
}
// Headers returns the headers used to create the stream
func (s *Stream) Headers() http.Header {
return s.headers
}
// String returns the string version of stream using the
// streamId to uniquely identify the stream
func (s *Stream) String() string {
return fmt.Sprintf("stream:%d", s.streamId)
}
// Identifier returns a 32 bit identifier for the stream
func (s *Stream) Identifier() uint32 {
return uint32(s.streamId)
}
// IsFinished returns whether the stream has finished
// sending data
func (s *Stream) IsFinished() bool {
return s.finished
}
// Implement net.Conn interface
func (s *Stream) LocalAddr() net.Addr {
return s.conn.conn.LocalAddr()
}
func (s *Stream) RemoteAddr() net.Addr {
return s.conn.conn.RemoteAddr()
}
// TODO set per stream values instead of connection-wide
func (s *Stream) SetDeadline(t time.Time) error {
return s.conn.conn.SetDeadline(t)
}
func (s *Stream) SetReadDeadline(t time.Time) error {
return s.conn.conn.SetReadDeadline(t)
}
func (s *Stream) SetWriteDeadline(t time.Time) error {
return s.conn.conn.SetWriteDeadline(t)
}
func (s *Stream) closeRemoteChannels() {
s.closeLock.Lock()
defer s.closeLock.Unlock()
select {
case <-s.closeChan:
default:
close(s.closeChan)
}
}

View File

@ -0,0 +1,16 @@
package spdystream
import (
"log"
"os"
)
var (
DEBUG = os.Getenv("DEBUG")
)
func debugMessage(fmt string, args ...interface{}) {
if DEBUG != "" {
log.Printf(fmt, args...)
}
}

View File

@ -38,6 +38,7 @@ import (
// DiscoveryInterface holds the methods that discover server-supported API groups, // DiscoveryInterface holds the methods that discover server-supported API groups,
// versions and resources. // versions and resources.
type DiscoveryInterface interface { type DiscoveryInterface interface {
RESTClient() rest.Interface
ServerGroupsInterface ServerGroupsInterface
ServerResourcesInterface ServerResourcesInterface
ServerVersionInterface ServerVersionInterface
@ -80,7 +81,7 @@ type SwaggerSchemaInterface interface {
// DiscoveryClient implements the functions that discover server-supported API groups, // DiscoveryClient implements the functions that discover server-supported API groups,
// versions and resources. // versions and resources.
type DiscoveryClient struct { type DiscoveryClient struct {
*rest.RESTClient restClient rest.Interface
LegacyPrefix string LegacyPrefix string
} }
@ -107,7 +108,7 @@ func apiVersionsToAPIGroup(apiVersions *unversioned.APIVersions) (apiGroup unver
func (d *DiscoveryClient) ServerGroups() (apiGroupList *unversioned.APIGroupList, err error) { func (d *DiscoveryClient) ServerGroups() (apiGroupList *unversioned.APIGroupList, err error) {
// Get the groupVersions exposed at /api // Get the groupVersions exposed at /api
v := &unversioned.APIVersions{} v := &unversioned.APIVersions{}
err = d.Get().AbsPath(d.LegacyPrefix).Do().Into(v) err = d.restClient.Get().AbsPath(d.LegacyPrefix).Do().Into(v)
apiGroup := unversioned.APIGroup{} apiGroup := unversioned.APIGroup{}
if err == nil { if err == nil {
apiGroup = apiVersionsToAPIGroup(v) apiGroup = apiVersionsToAPIGroup(v)
@ -118,7 +119,7 @@ func (d *DiscoveryClient) ServerGroups() (apiGroupList *unversioned.APIGroupList
// Get the groupVersions exposed at /apis // Get the groupVersions exposed at /apis
apiGroupList = &unversioned.APIGroupList{} apiGroupList = &unversioned.APIGroupList{}
err = d.Get().AbsPath("/apis").Do().Into(apiGroupList) err = d.restClient.Get().AbsPath("/apis").Do().Into(apiGroupList)
if err != nil && !errors.IsNotFound(err) && !errors.IsForbidden(err) { if err != nil && !errors.IsNotFound(err) && !errors.IsForbidden(err) {
return nil, err return nil, err
} }
@ -144,7 +145,7 @@ func (d *DiscoveryClient) ServerResourcesForGroupVersion(groupVersion string) (r
url.Path = "/apis/" + groupVersion url.Path = "/apis/" + groupVersion
} }
resources = &unversioned.APIResourceList{} resources = &unversioned.APIResourceList{}
err = d.Get().AbsPath(url.String()).Do().Into(resources) err = d.restClient.Get().AbsPath(url.String()).Do().Into(resources)
if err != nil { if err != nil {
// ignore 403 or 404 error to be compatible with an v1.0 server. // ignore 403 or 404 error to be compatible with an v1.0 server.
if groupVersion == "v1" && (errors.IsNotFound(err) || errors.IsForbidden(err)) { if groupVersion == "v1" && (errors.IsNotFound(err) || errors.IsForbidden(err)) {
@ -255,7 +256,7 @@ func (d *DiscoveryClient) ServerPreferredNamespacedResources() ([]unversioned.Gr
// ServerVersion retrieves and parses the server's version (git version). // ServerVersion retrieves and parses the server's version (git version).
func (d *DiscoveryClient) ServerVersion() (*version.Info, error) { func (d *DiscoveryClient) ServerVersion() (*version.Info, error) {
body, err := d.Get().AbsPath("/version").Do().Raw() body, err := d.restClient.Get().AbsPath("/version").Do().Raw()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -289,7 +290,7 @@ func (d *DiscoveryClient) SwaggerSchema(version unversioned.GroupVersion) (*swag
path = "/swaggerapi/apis/" + version.Group + "/" + version.Version path = "/swaggerapi/apis/" + version.Group + "/" + version.Version
} }
body, err := d.Get().AbsPath(path).Do().Raw() body, err := d.restClient.Get().AbsPath(path).Do().Raw()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -305,10 +306,7 @@ func setDiscoveryDefaults(config *rest.Config) error {
config.APIPath = "" config.APIPath = ""
config.GroupVersion = nil config.GroupVersion = nil
codec := runtime.NoopEncoder{Decoder: api.Codecs.UniversalDecoder()} codec := runtime.NoopEncoder{Decoder: api.Codecs.UniversalDecoder()}
config.NegotiatedSerializer = serializer.NegotiatedSerializerWrapper( config.NegotiatedSerializer = serializer.NegotiatedSerializerWrapper(runtime.SerializerInfo{Serializer: codec})
runtime.SerializerInfo{Serializer: codec},
runtime.StreamSerializerInfo{},
)
if len(config.UserAgent) == 0 { if len(config.UserAgent) == 0 {
config.UserAgent = rest.DefaultKubernetesUserAgent() config.UserAgent = rest.DefaultKubernetesUserAgent()
} }
@ -323,7 +321,7 @@ func NewDiscoveryClientForConfig(c *rest.Config) (*DiscoveryClient, error) {
return nil, err return nil, err
} }
client, err := rest.UnversionedRESTClientFor(&config) client, err := rest.UnversionedRESTClientFor(&config)
return &DiscoveryClient{RESTClient: client, LegacyPrefix: "/api"}, err return &DiscoveryClient{restClient: client, LegacyPrefix: "/api"}, err
} }
// NewDiscoveryClientForConfig creates a new DiscoveryClient for the given config. If // NewDiscoveryClientForConfig creates a new DiscoveryClient for the given config. If
@ -338,8 +336,8 @@ func NewDiscoveryClientForConfigOrDie(c *rest.Config) *DiscoveryClient {
} }
// New creates a new DiscoveryClient for the given RESTClient. // New creates a new DiscoveryClient for the given RESTClient.
func NewDiscoveryClient(c *rest.RESTClient) *DiscoveryClient { func NewDiscoveryClient(c rest.Interface) *DiscoveryClient {
return &DiscoveryClient{RESTClient: c, LegacyPrefix: "/api"} return &DiscoveryClient{restClient: c, LegacyPrefix: "/api"}
} }
func stringDoesntExistIn(str string, slice []string) bool { func stringDoesntExistIn(str string, slice []string) bool {
@ -350,3 +348,12 @@ func stringDoesntExistIn(str string, slice []string) bool {
} }
return true return true
} }
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *DiscoveryClient) RESTClient() rest.Interface {
if c == nil {
return nil
}
return c.restClient
}

View File

@ -21,6 +21,7 @@ import (
"k8s.io/client-go/pkg/api/unversioned" "k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/api/v1" "k8s.io/client-go/pkg/api/v1"
"k8s.io/client-go/pkg/version" "k8s.io/client-go/pkg/version"
"k8s.io/client-go/rest"
"k8s.io/client-go/testing" "k8s.io/client-go/testing"
) )
@ -80,3 +81,7 @@ func (c *FakeDiscovery) SwaggerSchema(version unversioned.GroupVersion) (*swagge
c.Invokes(action, nil) c.Invokes(action, nil)
return &swagger.ApiDeclaration{}, nil return &swagger.ApiDeclaration{}, nil
} }
func (c *FakeDiscovery) RESTClient() rest.Interface {
return nil
}

View File

@ -0,0 +1,135 @@
/*
Copyright 2016 The Kubernetes 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 discovery
import (
"fmt"
"k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/util/sets"
"k8s.io/client-go/pkg/version"
"k8s.io/client-go/rest"
// Import solely to initialize client auth plugins.
_ "k8s.io/client-go/plugin/pkg/client/auth"
)
// MatchesServerVersion queries the server to compares the build version
// (git hash) of the client with the server's build version. It returns an error
// if it failed to contact the server or if the versions are not an exact match.
func MatchesServerVersion(client DiscoveryInterface, c *rest.Config) error {
var err error
if client == nil {
client, err = NewDiscoveryClientForConfig(c)
if err != nil {
return err
}
}
cVer := version.Get()
sVer, err := client.ServerVersion()
if err != nil {
return fmt.Errorf("couldn't read version from server: %v\n", err)
}
// GitVersion includes GitCommit and GitTreeState, but best to be safe?
if cVer.GitVersion != sVer.GitVersion || cVer.GitCommit != sVer.GitCommit || cVer.GitTreeState != sVer.GitTreeState {
return fmt.Errorf("server version (%#v) differs from client version (%#v)!\n", sVer, cVer)
}
return nil
}
// NegotiateVersion queries the server's supported api versions to find
// a version that both client and server support.
// - If no version is provided, try registered client versions in order of
// preference.
// - If version is provided, but not default config (explicitly requested via
// commandline flag), and is unsupported by the server, print a warning to
// stderr and try client's registered versions in order of preference.
// - If version is config default, and the server does not support it,
// return an error.
func NegotiateVersion(client DiscoveryInterface, c *rest.Config, requestedGV *unversioned.GroupVersion, clientRegisteredGVs []unversioned.GroupVersion) (*unversioned.GroupVersion, error) {
var err error
if client == nil {
client, err = NewDiscoveryClientForConfig(c)
if err != nil {
return nil, err
}
}
clientVersions := sets.String{}
for _, gv := range clientRegisteredGVs {
clientVersions.Insert(gv.String())
}
groups, err := client.ServerGroups()
if err != nil {
// This is almost always a connection error, and higher level code should treat this as a generic error,
// not a negotiation specific error.
return nil, err
}
versions := unversioned.ExtractGroupVersions(groups)
serverVersions := sets.String{}
for _, v := range versions {
serverVersions.Insert(v)
}
// If no version requested, use config version (may also be empty).
// make a copy of the original so we don't risk mutating input here or in the returned value
var preferredGV *unversioned.GroupVersion
switch {
case requestedGV != nil:
t := *requestedGV
preferredGV = &t
case c.GroupVersion != nil:
t := *c.GroupVersion
preferredGV = &t
}
// If version explicitly requested verify that both client and server support it.
// If server does not support warn, but try to negotiate a lower version.
if preferredGV != nil {
if !clientVersions.Has(preferredGV.String()) {
return nil, fmt.Errorf("client does not support API version %q; client supported API versions: %v", preferredGV, clientVersions)
}
// If the server supports no versions, then we should just use the preferredGV
// This can happen because discovery fails due to 403 Forbidden errors
if len(serverVersions) == 0 {
return preferredGV, nil
}
if serverVersions.Has(preferredGV.String()) {
return preferredGV, nil
}
// If we are using an explicit config version the server does not support, fail.
if (c.GroupVersion != nil) && (*preferredGV == *c.GroupVersion) {
return nil, fmt.Errorf("server does not support API version %q", preferredGV)
}
}
for _, clientGV := range clientRegisteredGVs {
if serverVersions.Has(clientGV.String()) {
// Version was not explicitly requested in command config (--api-version).
// Ok to fall back to a supported version with a warning.
// TODO: caesarxuchao: enable the warning message when we have
// proper fix. Please refer to issue #14895.
// if len(version) != 0 {
// glog.Warningf("Server does not support API version '%s'. Falling back to '%s'.", version, clientVersion)
// }
t := clientGV
return &t, nil
}
}
return nil, fmt.Errorf("failed to negotiate an api version; server supports: %v, client supports: %v",
serverVersions, clientVersions)
}

View File

@ -0,0 +1,158 @@
/*
Copyright 2015 The Kubernetes 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 discovery_test
import (
"bytes"
"encoding/json"
"errors"
"io"
"io/ioutil"
"net/http"
"strings"
"testing"
"k8s.io/client-go/discovery"
"k8s.io/client-go/pkg/api"
"k8s.io/client-go/pkg/api/testapi"
uapi "k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/apimachinery/registered"
"k8s.io/client-go/pkg/runtime"
"k8s.io/client-go/rest"
"k8s.io/client-go/rest/fake"
)
func objBody(object interface{}) io.ReadCloser {
output, err := json.MarshalIndent(object, "", "")
if err != nil {
panic(err)
}
return ioutil.NopCloser(bytes.NewReader([]byte(output)))
}
func TestNegotiateVersion(t *testing.T) {
tests := []struct {
name string
version *uapi.GroupVersion
expectedVersion *uapi.GroupVersion
serverVersions []string
clientVersions []uapi.GroupVersion
config *rest.Config
expectErr func(err error) bool
sendErr error
statusCode int
}{
{
name: "server supports client default",
version: &uapi.GroupVersion{Version: "version1"},
config: &rest.Config{},
serverVersions: []string{"version1", registered.GroupOrDie(api.GroupName).GroupVersion.String()},
clientVersions: []uapi.GroupVersion{{Version: "version1"}, registered.GroupOrDie(api.GroupName).GroupVersion},
expectedVersion: &uapi.GroupVersion{Version: "version1"},
statusCode: http.StatusOK,
},
{
name: "server falls back to client supported",
version: &registered.GroupOrDie(api.GroupName).GroupVersion,
config: &rest.Config{},
serverVersions: []string{"version1"},
clientVersions: []uapi.GroupVersion{{Version: "version1"}, registered.GroupOrDie(api.GroupName).GroupVersion},
expectedVersion: &uapi.GroupVersion{Version: "version1"},
statusCode: http.StatusOK,
},
{
name: "explicit version supported",
config: &rest.Config{ContentConfig: rest.ContentConfig{GroupVersion: &registered.GroupOrDie(api.GroupName).GroupVersion}},
serverVersions: []string{"/version1", registered.GroupOrDie(api.GroupName).GroupVersion.String()},
clientVersions: []uapi.GroupVersion{{Version: "version1"}, registered.GroupOrDie(api.GroupName).GroupVersion},
expectedVersion: &registered.GroupOrDie(api.GroupName).GroupVersion,
statusCode: http.StatusOK,
},
{
name: "explicit version not supported",
config: &rest.Config{ContentConfig: rest.ContentConfig{GroupVersion: &registered.GroupOrDie(api.GroupName).GroupVersion}},
serverVersions: []string{"version1"},
clientVersions: []uapi.GroupVersion{{Version: "version1"}, registered.GroupOrDie(api.GroupName).GroupVersion},
expectErr: func(err error) bool { return strings.Contains(err.Error(), `server does not support API version "v1"`) },
statusCode: http.StatusOK,
},
{
name: "connection refused error",
config: &rest.Config{ContentConfig: rest.ContentConfig{GroupVersion: &registered.GroupOrDie(api.GroupName).GroupVersion}},
serverVersions: []string{"version1"},
clientVersions: []uapi.GroupVersion{{Version: "version1"}, registered.GroupOrDie(api.GroupName).GroupVersion},
sendErr: errors.New("connection refused"),
expectErr: func(err error) bool { return strings.Contains(err.Error(), "connection refused") },
statusCode: http.StatusOK,
},
{
name: "discovery fails due to 403 Forbidden errors and thus serverVersions is empty, use default GroupVersion",
config: &rest.Config{ContentConfig: rest.ContentConfig{GroupVersion: &registered.GroupOrDie(api.GroupName).GroupVersion}},
clientVersions: []uapi.GroupVersion{{Version: "version1"}, registered.GroupOrDie(api.GroupName).GroupVersion},
expectedVersion: &registered.GroupOrDie(api.GroupName).GroupVersion,
statusCode: http.StatusForbidden,
},
{
name: "discovery fails due to 404 Not Found errors and thus serverVersions is empty, use requested GroupVersion",
version: &uapi.GroupVersion{Version: "version1"},
config: &rest.Config{ContentConfig: rest.ContentConfig{GroupVersion: &registered.GroupOrDie(api.GroupName).GroupVersion}},
clientVersions: []uapi.GroupVersion{{Version: "version1"}, registered.GroupOrDie(api.GroupName).GroupVersion},
expectedVersion: &uapi.GroupVersion{Version: "version1"},
statusCode: http.StatusNotFound,
},
{
name: "discovery fails due to 403 Forbidden errors and thus serverVersions is empty, no fallback GroupVersion",
config: &rest.Config{},
clientVersions: []uapi.GroupVersion{{Version: "version1"}, registered.GroupOrDie(api.GroupName).GroupVersion},
expectErr: func(err error) bool { return strings.Contains(err.Error(), "failed to negotiate an api version;") },
statusCode: http.StatusForbidden,
},
}
for _, test := range tests {
fakeClient := &fake.RESTClient{
NegotiatedSerializer: testapi.Default.NegotiatedSerializer(),
Resp: &http.Response{
StatusCode: test.statusCode,
Body: objBody(&uapi.APIVersions{Versions: test.serverVersions}),
},
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
if test.sendErr != nil {
return nil, test.sendErr
}
header := http.Header{}
header.Set("Content-Type", runtime.ContentTypeJSON)
return &http.Response{StatusCode: test.statusCode, Header: header, Body: objBody(&uapi.APIVersions{Versions: test.serverVersions})}, nil
}),
}
c := discovery.NewDiscoveryClientForConfigOrDie(test.config)
c.RESTClient().(*rest.RESTClient).Client = fakeClient.Client
response, err := discovery.NegotiateVersion(c, test.config, test.version, test.clientVersions)
if err == nil && test.expectErr != nil {
t.Errorf("expected error, got nil for [%s].", test.name)
}
if err != nil {
if test.expectErr == nil || !test.expectErr(err) {
t.Errorf("unexpected error for [%s]: %v.", test.name, err)
}
continue
}
if *response != *test.expectedVersion {
t.Errorf("%s: expected version %s, got %s.", test.name, test.expectedVersion, response)
}
}
}

View File

@ -241,13 +241,22 @@ func (dynamicCodec) Encode(obj runtime.Object, w io.Writer) error {
// ContentConfig returns a rest.ContentConfig for dynamic types. // ContentConfig returns a rest.ContentConfig for dynamic types.
func ContentConfig() rest.ContentConfig { func ContentConfig() rest.ContentConfig {
// TODO: it's questionable that this should be using anything other than unstructured schema and JSON var jsonInfo runtime.SerializerInfo
codec := dynamicCodec{} // TODO: api.Codecs here should become "pkg/apis/server/scheme" which is the minimal core you need
streamingInfo, _ := api.Codecs.StreamingSerializerForMediaType("application/json;stream=watch", nil) // to talk to a kubernetes server
for _, info := range api.Codecs.SupportedMediaTypes() {
if info.MediaType == runtime.ContentTypeJSON {
jsonInfo = info
break
}
}
jsonInfo.Serializer = dynamicCodec{}
jsonInfo.PrettySerializer = nil
return rest.ContentConfig{ return rest.ContentConfig{
AcceptContentTypes: runtime.ContentTypeJSON, AcceptContentTypes: runtime.ContentTypeJSON,
ContentType: runtime.ContentTypeJSON, ContentType: runtime.ContentTypeJSON,
NegotiatedSerializer: serializer.NegotiatedSerializerWrapper(runtime.SerializerInfo{Serializer: codec}, streamingInfo), NegotiatedSerializer: serializer.NegotiatedSerializerWrapper(jsonInfo),
} }
} }

View File

@ -19,11 +19,8 @@ package dynamic
import ( import (
"sync" "sync"
"k8s.io/client-go/pkg/api"
"k8s.io/client-go/pkg/api/meta" "k8s.io/client-go/pkg/api/meta"
"k8s.io/client-go/pkg/api/unversioned" "k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/runtime"
"k8s.io/client-go/pkg/runtime/serializer"
"k8s.io/client-go/rest" "k8s.io/client-go/rest"
) )
@ -64,6 +61,7 @@ type clientPoolImpl struct {
// resources or groups. // resources or groups.
func NewClientPool(config *rest.Config, mapper meta.RESTMapper, apiPathResolverFunc APIPathResolverFunc) ClientPool { func NewClientPool(config *rest.Config, mapper meta.RESTMapper, apiPathResolverFunc APIPathResolverFunc) ClientPool {
confCopy := *config confCopy := *config
return &clientPoolImpl{ return &clientPoolImpl{
config: &confCopy, config: &confCopy,
clients: map[unversioned.GroupVersion]*Client{}, clients: map[unversioned.GroupVersion]*Client{},
@ -108,11 +106,6 @@ func (c *clientPoolImpl) ClientForGroupVersionKind(kind unversioned.GroupVersion
// we need to make a client // we need to make a client
conf.GroupVersion = &gv conf.GroupVersion = &gv
if conf.NegotiatedSerializer == nil {
streamingInfo, _ := api.Codecs.StreamingSerializerForMediaType("application/json;stream=watch", nil)
conf.NegotiatedSerializer = serializer.NegotiatedSerializerWrapper(runtime.SerializerInfo{Serializer: dynamicCodec{}}, streamingInfo)
}
dynamicClient, err := NewClient(conf) dynamicClient, err := NewClient(conf)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -529,6 +529,7 @@ func TestPatch(t *testing.T) {
return return
} }
w.Header().Set("Content-Type", "application/json")
w.Write(data) w.Write(data)
}) })
if err != nil { if err != nil {

View File

@ -242,7 +242,7 @@ func NewForConfigOrDie(c *rest.Config) *Clientset {
} }
// New creates a new Clientset for the given RESTClient. // New creates a new Clientset for the given RESTClient.
func New(c *rest.RESTClient) *Clientset { func New(c rest.Interface) *Clientset {
var clientset Clientset var clientset Clientset
clientset.CoreClient = v1core.New(c) clientset.CoreClient = v1core.New(c)
clientset.AppsClient = v1alpha1apps.New(c) clientset.AppsClient = v1alpha1apps.New(c)

View File

@ -24,17 +24,17 @@ import (
) )
type AppsInterface interface { type AppsInterface interface {
GetRESTClient() *rest.RESTClient RESTClient() rest.Interface
PetSetsGetter StatefulSetsGetter
} }
// AppsClient is used to interact with features provided by the Apps group. // AppsClient is used to interact with features provided by the Apps group.
type AppsClient struct { type AppsClient struct {
*rest.RESTClient restClient rest.Interface
} }
func (c *AppsClient) PetSets(namespace string) PetSetInterface { func (c *AppsClient) StatefulSets(namespace string) StatefulSetInterface {
return newPetSets(c, namespace) return newStatefulSets(c, namespace)
} }
// NewForConfig creates a new AppsClient for the given config. // NewForConfig creates a new AppsClient for the given config.
@ -61,7 +61,7 @@ func NewForConfigOrDie(c *rest.Config) *AppsClient {
} }
// New creates a new AppsClient for the given RESTClient. // New creates a new AppsClient for the given RESTClient.
func New(c *rest.RESTClient) *AppsClient { func New(c rest.Interface) *AppsClient {
return &AppsClient{c} return &AppsClient{c}
} }
@ -86,11 +86,11 @@ func setConfigDefaults(config *rest.Config) error {
return nil return nil
} }
// GetRESTClient returns a RESTClient that is used to communicate // RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation. // with API server by this client implementation.
func (c *AppsClient) GetRESTClient() *rest.RESTClient { func (c *AppsClient) RESTClient() rest.Interface {
if c == nil { if c == nil {
return nil return nil
} }
return c.RESTClient return c.restClient
} }

View File

@ -26,12 +26,13 @@ type FakeApps struct {
*testing.Fake *testing.Fake
} }
func (c *FakeApps) PetSets(namespace string) v1alpha1.PetSetInterface { func (c *FakeApps) StatefulSets(namespace string) v1alpha1.StatefulSetInterface {
return &FakePetSets{c, namespace} return &FakeStatefulSets{c, namespace}
} }
// GetRESTClient returns a RESTClient that is used to communicate // RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation. // with API server by this client implementation.
func (c *FakeApps) GetRESTClient() *rest.RESTClient { func (c *FakeApps) RESTClient() rest.Interface {
return nil var ret *rest.RESTClient
return ret
} }

View File

@ -1,128 +0,0 @@
/*
Copyright 2016 The Kubernetes 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 fake
import (
api "k8s.io/client-go/pkg/api"
unversioned "k8s.io/client-go/pkg/api/unversioned"
v1 "k8s.io/client-go/pkg/api/v1"
v1alpha1 "k8s.io/client-go/pkg/apis/apps/v1alpha1"
labels "k8s.io/client-go/pkg/labels"
watch "k8s.io/client-go/pkg/watch"
testing "k8s.io/client-go/testing"
)
// FakePetSets implements PetSetInterface
type FakePetSets struct {
Fake *FakeApps
ns string
}
var petsetsResource = unversioned.GroupVersionResource{Group: "apps", Version: "v1alpha1", Resource: "petsets"}
func (c *FakePetSets) Create(petSet *v1alpha1.PetSet) (result *v1alpha1.PetSet, err error) {
obj, err := c.Fake.
Invokes(testing.NewCreateAction(petsetsResource, c.ns, petSet), &v1alpha1.PetSet{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.PetSet), err
}
func (c *FakePetSets) Update(petSet *v1alpha1.PetSet) (result *v1alpha1.PetSet, err error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateAction(petsetsResource, c.ns, petSet), &v1alpha1.PetSet{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.PetSet), err
}
func (c *FakePetSets) UpdateStatus(petSet *v1alpha1.PetSet) (*v1alpha1.PetSet, error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateSubresourceAction(petsetsResource, "status", c.ns, petSet), &v1alpha1.PetSet{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.PetSet), err
}
func (c *FakePetSets) Delete(name string, options *v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(petsetsResource, c.ns, name), &v1alpha1.PetSet{})
return err
}
func (c *FakePetSets) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
action := testing.NewDeleteCollectionAction(petsetsResource, c.ns, listOptions)
_, err := c.Fake.Invokes(action, &v1alpha1.PetSetList{})
return err
}
func (c *FakePetSets) Get(name string) (result *v1alpha1.PetSet, err error) {
obj, err := c.Fake.
Invokes(testing.NewGetAction(petsetsResource, c.ns, name), &v1alpha1.PetSet{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.PetSet), err
}
func (c *FakePetSets) List(opts v1.ListOptions) (result *v1alpha1.PetSetList, err error) {
obj, err := c.Fake.
Invokes(testing.NewListAction(petsetsResource, c.ns, opts), &v1alpha1.PetSetList{})
if obj == nil {
return nil, err
}
label, _, _ := testing.ExtractFromListOptions(opts)
if label == nil {
label = labels.Everything()
}
list := &v1alpha1.PetSetList{}
for _, item := range obj.(*v1alpha1.PetSetList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)
}
}
return list, err
}
// Watch returns a watch.Interface that watches the requested petSets.
func (c *FakePetSets) Watch(opts v1.ListOptions) (watch.Interface, error) {
return c.Fake.
InvokesWatch(testing.NewWatchAction(petsetsResource, c.ns, opts))
}
// Patch applies the patch and returns the patched petSet.
func (c *FakePetSets) Patch(name string, pt api.PatchType, data []byte, subresources ...string) (result *v1alpha1.PetSet, err error) {
obj, err := c.Fake.
Invokes(testing.NewPatchSubresourceAction(petsetsResource, c.ns, name, data, subresources...), &v1alpha1.PetSet{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.PetSet), err
}

View File

@ -0,0 +1,128 @@
/*
Copyright 2016 The Kubernetes 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 fake
import (
api "k8s.io/client-go/pkg/api"
unversioned "k8s.io/client-go/pkg/api/unversioned"
v1 "k8s.io/client-go/pkg/api/v1"
v1alpha1 "k8s.io/client-go/pkg/apis/apps/v1alpha1"
labels "k8s.io/client-go/pkg/labels"
watch "k8s.io/client-go/pkg/watch"
testing "k8s.io/client-go/testing"
)
// FakeStatefulSets implements StatefulSetInterface
type FakeStatefulSets struct {
Fake *FakeApps
ns string
}
var statefulsetsResource = unversioned.GroupVersionResource{Group: "apps", Version: "v1alpha1", Resource: "statefulsets"}
func (c *FakeStatefulSets) Create(statefulSet *v1alpha1.StatefulSet) (result *v1alpha1.StatefulSet, err error) {
obj, err := c.Fake.
Invokes(testing.NewCreateAction(statefulsetsResource, c.ns, statefulSet), &v1alpha1.StatefulSet{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.StatefulSet), err
}
func (c *FakeStatefulSets) Update(statefulSet *v1alpha1.StatefulSet) (result *v1alpha1.StatefulSet, err error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateAction(statefulsetsResource, c.ns, statefulSet), &v1alpha1.StatefulSet{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.StatefulSet), err
}
func (c *FakeStatefulSets) UpdateStatus(statefulSet *v1alpha1.StatefulSet) (*v1alpha1.StatefulSet, error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateSubresourceAction(statefulsetsResource, "status", c.ns, statefulSet), &v1alpha1.StatefulSet{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.StatefulSet), err
}
func (c *FakeStatefulSets) Delete(name string, options *v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(statefulsetsResource, c.ns, name), &v1alpha1.StatefulSet{})
return err
}
func (c *FakeStatefulSets) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
action := testing.NewDeleteCollectionAction(statefulsetsResource, c.ns, listOptions)
_, err := c.Fake.Invokes(action, &v1alpha1.StatefulSetList{})
return err
}
func (c *FakeStatefulSets) Get(name string) (result *v1alpha1.StatefulSet, err error) {
obj, err := c.Fake.
Invokes(testing.NewGetAction(statefulsetsResource, c.ns, name), &v1alpha1.StatefulSet{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.StatefulSet), err
}
func (c *FakeStatefulSets) List(opts v1.ListOptions) (result *v1alpha1.StatefulSetList, err error) {
obj, err := c.Fake.
Invokes(testing.NewListAction(statefulsetsResource, c.ns, opts), &v1alpha1.StatefulSetList{})
if obj == nil {
return nil, err
}
label, _, _ := testing.ExtractFromListOptions(opts)
if label == nil {
label = labels.Everything()
}
list := &v1alpha1.StatefulSetList{}
for _, item := range obj.(*v1alpha1.StatefulSetList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)
}
}
return list, err
}
// Watch returns a watch.Interface that watches the requested statefulSets.
func (c *FakeStatefulSets) Watch(opts v1.ListOptions) (watch.Interface, error) {
return c.Fake.
InvokesWatch(testing.NewWatchAction(statefulsetsResource, c.ns, opts))
}
// Patch applies the patch and returns the patched statefulSet.
func (c *FakeStatefulSets) Patch(name string, pt api.PatchType, data []byte, subresources ...string) (result *v1alpha1.StatefulSet, err error) {
obj, err := c.Fake.
Invokes(testing.NewPatchSubresourceAction(statefulsetsResource, c.ns, name, data, subresources...), &v1alpha1.StatefulSet{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.StatefulSet), err
}

View File

@ -16,4 +16,4 @@ limitations under the License.
package v1alpha1 package v1alpha1
type PetSetExpansion interface{} type StatefulSetExpansion interface{}

View File

@ -1,166 +0,0 @@
/*
Copyright 2016 The Kubernetes 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 v1alpha1
import (
api "k8s.io/client-go/pkg/api"
v1 "k8s.io/client-go/pkg/api/v1"
v1alpha1 "k8s.io/client-go/pkg/apis/apps/v1alpha1"
watch "k8s.io/client-go/pkg/watch"
)
// PetSetsGetter has a method to return a PetSetInterface.
// A group's client should implement this interface.
type PetSetsGetter interface {
PetSets(namespace string) PetSetInterface
}
// PetSetInterface has methods to work with PetSet resources.
type PetSetInterface interface {
Create(*v1alpha1.PetSet) (*v1alpha1.PetSet, error)
Update(*v1alpha1.PetSet) (*v1alpha1.PetSet, error)
UpdateStatus(*v1alpha1.PetSet) (*v1alpha1.PetSet, error)
Delete(name string, options *v1.DeleteOptions) error
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
Get(name string) (*v1alpha1.PetSet, error)
List(opts v1.ListOptions) (*v1alpha1.PetSetList, error)
Watch(opts v1.ListOptions) (watch.Interface, error)
Patch(name string, pt api.PatchType, data []byte, subresources ...string) (result *v1alpha1.PetSet, err error)
PetSetExpansion
}
// petSets implements PetSetInterface
type petSets struct {
client *AppsClient
ns string
}
// newPetSets returns a PetSets
func newPetSets(c *AppsClient, namespace string) *petSets {
return &petSets{
client: c,
ns: namespace,
}
}
// Create takes the representation of a petSet and creates it. Returns the server's representation of the petSet, and an error, if there is any.
func (c *petSets) Create(petSet *v1alpha1.PetSet) (result *v1alpha1.PetSet, err error) {
result = &v1alpha1.PetSet{}
err = c.client.Post().
Namespace(c.ns).
Resource("petsets").
Body(petSet).
Do().
Into(result)
return
}
// Update takes the representation of a petSet and updates it. Returns the server's representation of the petSet, and an error, if there is any.
func (c *petSets) Update(petSet *v1alpha1.PetSet) (result *v1alpha1.PetSet, err error) {
result = &v1alpha1.PetSet{}
err = c.client.Put().
Namespace(c.ns).
Resource("petsets").
Name(petSet.Name).
Body(petSet).
Do().
Into(result)
return
}
func (c *petSets) UpdateStatus(petSet *v1alpha1.PetSet) (result *v1alpha1.PetSet, err error) {
result = &v1alpha1.PetSet{}
err = c.client.Put().
Namespace(c.ns).
Resource("petsets").
Name(petSet.Name).
SubResource("status").
Body(petSet).
Do().
Into(result)
return
}
// Delete takes name of the petSet and deletes it. Returns an error if one occurs.
func (c *petSets) Delete(name string, options *v1.DeleteOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("petsets").
Name(name).
Body(options).
Do().
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *petSets) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("petsets").
VersionedParams(&listOptions, api.ParameterCodec).
Body(options).
Do().
Error()
}
// Get takes name of the petSet, and returns the corresponding petSet object, and an error if there is any.
func (c *petSets) Get(name string) (result *v1alpha1.PetSet, err error) {
result = &v1alpha1.PetSet{}
err = c.client.Get().
Namespace(c.ns).
Resource("petsets").
Name(name).
Do().
Into(result)
return
}
// List takes label and field selectors, and returns the list of PetSets that match those selectors.
func (c *petSets) List(opts v1.ListOptions) (result *v1alpha1.PetSetList, err error) {
result = &v1alpha1.PetSetList{}
err = c.client.Get().
Namespace(c.ns).
Resource("petsets").
VersionedParams(&opts, api.ParameterCodec).
Do().
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested petSets.
func (c *petSets) Watch(opts v1.ListOptions) (watch.Interface, error) {
return c.client.Get().
Prefix("watch").
Namespace(c.ns).
Resource("petsets").
VersionedParams(&opts, api.ParameterCodec).
Watch()
}
// Patch applies the patch and returns the patched petSet.
func (c *petSets) Patch(name string, pt api.PatchType, data []byte, subresources ...string) (result *v1alpha1.PetSet, err error) {
result = &v1alpha1.PetSet{}
err = c.client.Patch(pt).
Namespace(c.ns).
Resource("petsets").
SubResource(subresources...).
Name(name).
Body(data).
Do().
Into(result)
return
}

View File

@ -0,0 +1,167 @@
/*
Copyright 2016 The Kubernetes 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 v1alpha1
import (
api "k8s.io/client-go/pkg/api"
v1 "k8s.io/client-go/pkg/api/v1"
v1alpha1 "k8s.io/client-go/pkg/apis/apps/v1alpha1"
watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
)
// StatefulSetsGetter has a method to return a StatefulSetInterface.
// A group's client should implement this interface.
type StatefulSetsGetter interface {
StatefulSets(namespace string) StatefulSetInterface
}
// StatefulSetInterface has methods to work with StatefulSet resources.
type StatefulSetInterface interface {
Create(*v1alpha1.StatefulSet) (*v1alpha1.StatefulSet, error)
Update(*v1alpha1.StatefulSet) (*v1alpha1.StatefulSet, error)
UpdateStatus(*v1alpha1.StatefulSet) (*v1alpha1.StatefulSet, error)
Delete(name string, options *v1.DeleteOptions) error
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
Get(name string) (*v1alpha1.StatefulSet, error)
List(opts v1.ListOptions) (*v1alpha1.StatefulSetList, error)
Watch(opts v1.ListOptions) (watch.Interface, error)
Patch(name string, pt api.PatchType, data []byte, subresources ...string) (result *v1alpha1.StatefulSet, err error)
StatefulSetExpansion
}
// statefulSets implements StatefulSetInterface
type statefulSets struct {
client rest.Interface
ns string
}
// newStatefulSets returns a StatefulSets
func newStatefulSets(c *AppsClient, namespace string) *statefulSets {
return &statefulSets{
client: c.RESTClient(),
ns: namespace,
}
}
// Create takes the representation of a statefulSet and creates it. Returns the server's representation of the statefulSet, and an error, if there is any.
func (c *statefulSets) Create(statefulSet *v1alpha1.StatefulSet) (result *v1alpha1.StatefulSet, err error) {
result = &v1alpha1.StatefulSet{}
err = c.client.Post().
Namespace(c.ns).
Resource("statefulsets").
Body(statefulSet).
Do().
Into(result)
return
}
// Update takes the representation of a statefulSet and updates it. Returns the server's representation of the statefulSet, and an error, if there is any.
func (c *statefulSets) Update(statefulSet *v1alpha1.StatefulSet) (result *v1alpha1.StatefulSet, err error) {
result = &v1alpha1.StatefulSet{}
err = c.client.Put().
Namespace(c.ns).
Resource("statefulsets").
Name(statefulSet.Name).
Body(statefulSet).
Do().
Into(result)
return
}
func (c *statefulSets) UpdateStatus(statefulSet *v1alpha1.StatefulSet) (result *v1alpha1.StatefulSet, err error) {
result = &v1alpha1.StatefulSet{}
err = c.client.Put().
Namespace(c.ns).
Resource("statefulsets").
Name(statefulSet.Name).
SubResource("status").
Body(statefulSet).
Do().
Into(result)
return
}
// Delete takes name of the statefulSet and deletes it. Returns an error if one occurs.
func (c *statefulSets) Delete(name string, options *v1.DeleteOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("statefulsets").
Name(name).
Body(options).
Do().
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *statefulSets) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("statefulsets").
VersionedParams(&listOptions, api.ParameterCodec).
Body(options).
Do().
Error()
}
// Get takes name of the statefulSet, and returns the corresponding statefulSet object, and an error if there is any.
func (c *statefulSets) Get(name string) (result *v1alpha1.StatefulSet, err error) {
result = &v1alpha1.StatefulSet{}
err = c.client.Get().
Namespace(c.ns).
Resource("statefulsets").
Name(name).
Do().
Into(result)
return
}
// List takes label and field selectors, and returns the list of StatefulSets that match those selectors.
func (c *statefulSets) List(opts v1.ListOptions) (result *v1alpha1.StatefulSetList, err error) {
result = &v1alpha1.StatefulSetList{}
err = c.client.Get().
Namespace(c.ns).
Resource("statefulsets").
VersionedParams(&opts, api.ParameterCodec).
Do().
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested statefulSets.
func (c *statefulSets) Watch(opts v1.ListOptions) (watch.Interface, error) {
return c.client.Get().
Prefix("watch").
Namespace(c.ns).
Resource("statefulsets").
VersionedParams(&opts, api.ParameterCodec).
Watch()
}
// Patch applies the patch and returns the patched statefulSet.
func (c *statefulSets) Patch(name string, pt api.PatchType, data []byte, subresources ...string) (result *v1alpha1.StatefulSet, err error) {
result = &v1alpha1.StatefulSet{}
err = c.client.Patch(pt).
Namespace(c.ns).
Resource("statefulsets").
SubResource(subresources...).
Name(name).
Body(data).
Do().
Into(result)
return
}

View File

@ -24,13 +24,13 @@ import (
) )
type AuthenticationInterface interface { type AuthenticationInterface interface {
GetRESTClient() *rest.RESTClient RESTClient() rest.Interface
TokenReviewsGetter TokenReviewsGetter
} }
// AuthenticationClient is used to interact with features provided by the Authentication group. // AuthenticationClient is used to interact with features provided by the Authentication group.
type AuthenticationClient struct { type AuthenticationClient struct {
*rest.RESTClient restClient rest.Interface
} }
func (c *AuthenticationClient) TokenReviews() TokenReviewInterface { func (c *AuthenticationClient) TokenReviews() TokenReviewInterface {
@ -61,7 +61,7 @@ func NewForConfigOrDie(c *rest.Config) *AuthenticationClient {
} }
// New creates a new AuthenticationClient for the given RESTClient. // New creates a new AuthenticationClient for the given RESTClient.
func New(c *rest.RESTClient) *AuthenticationClient { func New(c rest.Interface) *AuthenticationClient {
return &AuthenticationClient{c} return &AuthenticationClient{c}
} }
@ -86,11 +86,11 @@ func setConfigDefaults(config *rest.Config) error {
return nil return nil
} }
// GetRESTClient returns a RESTClient that is used to communicate // RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation. // with API server by this client implementation.
func (c *AuthenticationClient) GetRESTClient() *rest.RESTClient { func (c *AuthenticationClient) RESTClient() rest.Interface {
if c == nil { if c == nil {
return nil return nil
} }
return c.RESTClient return c.restClient
} }

View File

@ -30,8 +30,9 @@ func (c *FakeAuthentication) TokenReviews() v1beta1.TokenReviewInterface {
return &FakeTokenReviews{c} return &FakeTokenReviews{c}
} }
// GetRESTClient returns a RESTClient that is used to communicate // RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation. // with API server by this client implementation.
func (c *FakeAuthentication) GetRESTClient() *rest.RESTClient { func (c *FakeAuthentication) RESTClient() rest.Interface {
return nil var ret *rest.RESTClient
return ret
} }

View File

@ -16,6 +16,10 @@ limitations under the License.
package v1beta1 package v1beta1
import (
rest "k8s.io/client-go/rest"
)
// TokenReviewsGetter has a method to return a TokenReviewInterface. // TokenReviewsGetter has a method to return a TokenReviewInterface.
// A group's client should implement this interface. // A group's client should implement this interface.
type TokenReviewsGetter interface { type TokenReviewsGetter interface {
@ -29,12 +33,12 @@ type TokenReviewInterface interface {
// tokenReviews implements TokenReviewInterface // tokenReviews implements TokenReviewInterface
type tokenReviews struct { type tokenReviews struct {
client *AuthenticationClient client rest.Interface
} }
// newTokenReviews returns a TokenReviews // newTokenReviews returns a TokenReviews
func newTokenReviews(c *AuthenticationClient) *tokenReviews { func newTokenReviews(c *AuthenticationClient) *tokenReviews {
return &tokenReviews{ return &tokenReviews{
client: c, client: c.RESTClient(),
} }
} }

View File

@ -24,7 +24,7 @@ import (
) )
type AuthorizationInterface interface { type AuthorizationInterface interface {
GetRESTClient() *rest.RESTClient RESTClient() rest.Interface
LocalSubjectAccessReviewsGetter LocalSubjectAccessReviewsGetter
SelfSubjectAccessReviewsGetter SelfSubjectAccessReviewsGetter
SubjectAccessReviewsGetter SubjectAccessReviewsGetter
@ -32,7 +32,7 @@ type AuthorizationInterface interface {
// AuthorizationClient is used to interact with features provided by the Authorization group. // AuthorizationClient is used to interact with features provided by the Authorization group.
type AuthorizationClient struct { type AuthorizationClient struct {
*rest.RESTClient restClient rest.Interface
} }
func (c *AuthorizationClient) LocalSubjectAccessReviews(namespace string) LocalSubjectAccessReviewInterface { func (c *AuthorizationClient) LocalSubjectAccessReviews(namespace string) LocalSubjectAccessReviewInterface {
@ -71,7 +71,7 @@ func NewForConfigOrDie(c *rest.Config) *AuthorizationClient {
} }
// New creates a new AuthorizationClient for the given RESTClient. // New creates a new AuthorizationClient for the given RESTClient.
func New(c *rest.RESTClient) *AuthorizationClient { func New(c rest.Interface) *AuthorizationClient {
return &AuthorizationClient{c} return &AuthorizationClient{c}
} }
@ -96,11 +96,11 @@ func setConfigDefaults(config *rest.Config) error {
return nil return nil
} }
// GetRESTClient returns a RESTClient that is used to communicate // RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation. // with API server by this client implementation.
func (c *AuthorizationClient) GetRESTClient() *rest.RESTClient { func (c *AuthorizationClient) RESTClient() rest.Interface {
if c == nil { if c == nil {
return nil return nil
} }
return c.RESTClient return c.restClient
} }

View File

@ -38,8 +38,9 @@ func (c *FakeAuthorization) SubjectAccessReviews() v1beta1.SubjectAccessReviewIn
return &FakeSubjectAccessReviews{c} return &FakeSubjectAccessReviews{c}
} }
// GetRESTClient returns a RESTClient that is used to communicate // RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation. // with API server by this client implementation.
func (c *FakeAuthorization) GetRESTClient() *rest.RESTClient { func (c *FakeAuthorization) RESTClient() rest.Interface {
return nil var ret *rest.RESTClient
return ret
} }

View File

@ -16,6 +16,10 @@ limitations under the License.
package v1beta1 package v1beta1
import (
rest "k8s.io/client-go/rest"
)
// LocalSubjectAccessReviewsGetter has a method to return a LocalSubjectAccessReviewInterface. // LocalSubjectAccessReviewsGetter has a method to return a LocalSubjectAccessReviewInterface.
// A group's client should implement this interface. // A group's client should implement this interface.
type LocalSubjectAccessReviewsGetter interface { type LocalSubjectAccessReviewsGetter interface {
@ -29,14 +33,14 @@ type LocalSubjectAccessReviewInterface interface {
// localSubjectAccessReviews implements LocalSubjectAccessReviewInterface // localSubjectAccessReviews implements LocalSubjectAccessReviewInterface
type localSubjectAccessReviews struct { type localSubjectAccessReviews struct {
client *AuthorizationClient client rest.Interface
ns string ns string
} }
// newLocalSubjectAccessReviews returns a LocalSubjectAccessReviews // newLocalSubjectAccessReviews returns a LocalSubjectAccessReviews
func newLocalSubjectAccessReviews(c *AuthorizationClient, namespace string) *localSubjectAccessReviews { func newLocalSubjectAccessReviews(c *AuthorizationClient, namespace string) *localSubjectAccessReviews {
return &localSubjectAccessReviews{ return &localSubjectAccessReviews{
client: c, client: c.RESTClient(),
ns: namespace, ns: namespace,
} }
} }

View File

@ -16,6 +16,10 @@ limitations under the License.
package v1beta1 package v1beta1
import (
rest "k8s.io/client-go/rest"
)
// SelfSubjectAccessReviewsGetter has a method to return a SelfSubjectAccessReviewInterface. // SelfSubjectAccessReviewsGetter has a method to return a SelfSubjectAccessReviewInterface.
// A group's client should implement this interface. // A group's client should implement this interface.
type SelfSubjectAccessReviewsGetter interface { type SelfSubjectAccessReviewsGetter interface {
@ -29,12 +33,12 @@ type SelfSubjectAccessReviewInterface interface {
// selfSubjectAccessReviews implements SelfSubjectAccessReviewInterface // selfSubjectAccessReviews implements SelfSubjectAccessReviewInterface
type selfSubjectAccessReviews struct { type selfSubjectAccessReviews struct {
client *AuthorizationClient client rest.Interface
} }
// newSelfSubjectAccessReviews returns a SelfSubjectAccessReviews // newSelfSubjectAccessReviews returns a SelfSubjectAccessReviews
func newSelfSubjectAccessReviews(c *AuthorizationClient) *selfSubjectAccessReviews { func newSelfSubjectAccessReviews(c *AuthorizationClient) *selfSubjectAccessReviews {
return &selfSubjectAccessReviews{ return &selfSubjectAccessReviews{
client: c, client: c.RESTClient(),
} }
} }

View File

@ -16,6 +16,10 @@ limitations under the License.
package v1beta1 package v1beta1
import (
rest "k8s.io/client-go/rest"
)
// SubjectAccessReviewsGetter has a method to return a SubjectAccessReviewInterface. // SubjectAccessReviewsGetter has a method to return a SubjectAccessReviewInterface.
// A group's client should implement this interface. // A group's client should implement this interface.
type SubjectAccessReviewsGetter interface { type SubjectAccessReviewsGetter interface {
@ -29,12 +33,12 @@ type SubjectAccessReviewInterface interface {
// subjectAccessReviews implements SubjectAccessReviewInterface // subjectAccessReviews implements SubjectAccessReviewInterface
type subjectAccessReviews struct { type subjectAccessReviews struct {
client *AuthorizationClient client rest.Interface
} }
// newSubjectAccessReviews returns a SubjectAccessReviews // newSubjectAccessReviews returns a SubjectAccessReviews
func newSubjectAccessReviews(c *AuthorizationClient) *subjectAccessReviews { func newSubjectAccessReviews(c *AuthorizationClient) *subjectAccessReviews {
return &subjectAccessReviews{ return &subjectAccessReviews{
client: c, client: c.RESTClient(),
} }
} }

View File

@ -24,13 +24,13 @@ import (
) )
type AutoscalingInterface interface { type AutoscalingInterface interface {
GetRESTClient() *rest.RESTClient RESTClient() rest.Interface
HorizontalPodAutoscalersGetter HorizontalPodAutoscalersGetter
} }
// AutoscalingClient is used to interact with features provided by the Autoscaling group. // AutoscalingClient is used to interact with features provided by the Autoscaling group.
type AutoscalingClient struct { type AutoscalingClient struct {
*rest.RESTClient restClient rest.Interface
} }
func (c *AutoscalingClient) HorizontalPodAutoscalers(namespace string) HorizontalPodAutoscalerInterface { func (c *AutoscalingClient) HorizontalPodAutoscalers(namespace string) HorizontalPodAutoscalerInterface {
@ -61,7 +61,7 @@ func NewForConfigOrDie(c *rest.Config) *AutoscalingClient {
} }
// New creates a new AutoscalingClient for the given RESTClient. // New creates a new AutoscalingClient for the given RESTClient.
func New(c *rest.RESTClient) *AutoscalingClient { func New(c rest.Interface) *AutoscalingClient {
return &AutoscalingClient{c} return &AutoscalingClient{c}
} }
@ -86,11 +86,11 @@ func setConfigDefaults(config *rest.Config) error {
return nil return nil
} }
// GetRESTClient returns a RESTClient that is used to communicate // RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation. // with API server by this client implementation.
func (c *AutoscalingClient) GetRESTClient() *rest.RESTClient { func (c *AutoscalingClient) RESTClient() rest.Interface {
if c == nil { if c == nil {
return nil return nil
} }
return c.RESTClient return c.restClient
} }

View File

@ -30,8 +30,9 @@ func (c *FakeAutoscaling) HorizontalPodAutoscalers(namespace string) v1.Horizont
return &FakeHorizontalPodAutoscalers{c, namespace} return &FakeHorizontalPodAutoscalers{c, namespace}
} }
// GetRESTClient returns a RESTClient that is used to communicate // RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation. // with API server by this client implementation.
func (c *FakeAutoscaling) GetRESTClient() *rest.RESTClient { func (c *FakeAutoscaling) RESTClient() rest.Interface {
return nil var ret *rest.RESTClient
return ret
} }

View File

@ -21,6 +21,7 @@ import (
api_v1 "k8s.io/client-go/pkg/api/v1" api_v1 "k8s.io/client-go/pkg/api/v1"
v1 "k8s.io/client-go/pkg/apis/autoscaling/v1" v1 "k8s.io/client-go/pkg/apis/autoscaling/v1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// HorizontalPodAutoscalersGetter has a method to return a HorizontalPodAutoscalerInterface. // HorizontalPodAutoscalersGetter has a method to return a HorizontalPodAutoscalerInterface.
@ -45,14 +46,14 @@ type HorizontalPodAutoscalerInterface interface {
// horizontalPodAutoscalers implements HorizontalPodAutoscalerInterface // horizontalPodAutoscalers implements HorizontalPodAutoscalerInterface
type horizontalPodAutoscalers struct { type horizontalPodAutoscalers struct {
client *AutoscalingClient client rest.Interface
ns string ns string
} }
// newHorizontalPodAutoscalers returns a HorizontalPodAutoscalers // newHorizontalPodAutoscalers returns a HorizontalPodAutoscalers
func newHorizontalPodAutoscalers(c *AutoscalingClient, namespace string) *horizontalPodAutoscalers { func newHorizontalPodAutoscalers(c *AutoscalingClient, namespace string) *horizontalPodAutoscalers {
return &horizontalPodAutoscalers{ return &horizontalPodAutoscalers{
client: c, client: c.RESTClient(),
ns: namespace, ns: namespace,
} }
} }

View File

@ -24,13 +24,13 @@ import (
) )
type BatchInterface interface { type BatchInterface interface {
GetRESTClient() *rest.RESTClient RESTClient() rest.Interface
JobsGetter JobsGetter
} }
// BatchClient is used to interact with features provided by the Batch group. // BatchClient is used to interact with features provided by the Batch group.
type BatchClient struct { type BatchClient struct {
*rest.RESTClient restClient rest.Interface
} }
func (c *BatchClient) Jobs(namespace string) JobInterface { func (c *BatchClient) Jobs(namespace string) JobInterface {
@ -61,7 +61,7 @@ func NewForConfigOrDie(c *rest.Config) *BatchClient {
} }
// New creates a new BatchClient for the given RESTClient. // New creates a new BatchClient for the given RESTClient.
func New(c *rest.RESTClient) *BatchClient { func New(c rest.Interface) *BatchClient {
return &BatchClient{c} return &BatchClient{c}
} }
@ -86,11 +86,11 @@ func setConfigDefaults(config *rest.Config) error {
return nil return nil
} }
// GetRESTClient returns a RESTClient that is used to communicate // RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation. // with API server by this client implementation.
func (c *BatchClient) GetRESTClient() *rest.RESTClient { func (c *BatchClient) RESTClient() rest.Interface {
if c == nil { if c == nil {
return nil return nil
} }
return c.RESTClient return c.restClient
} }

View File

@ -30,8 +30,9 @@ func (c *FakeBatch) Jobs(namespace string) v1.JobInterface {
return &FakeJobs{c, namespace} return &FakeJobs{c, namespace}
} }
// GetRESTClient returns a RESTClient that is used to communicate // RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation. // with API server by this client implementation.
func (c *FakeBatch) GetRESTClient() *rest.RESTClient { func (c *FakeBatch) RESTClient() rest.Interface {
return nil var ret *rest.RESTClient
return ret
} }

View File

@ -21,6 +21,7 @@ import (
api_v1 "k8s.io/client-go/pkg/api/v1" api_v1 "k8s.io/client-go/pkg/api/v1"
v1 "k8s.io/client-go/pkg/apis/batch/v1" v1 "k8s.io/client-go/pkg/apis/batch/v1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// JobsGetter has a method to return a JobInterface. // JobsGetter has a method to return a JobInterface.
@ -45,14 +46,14 @@ type JobInterface interface {
// jobs implements JobInterface // jobs implements JobInterface
type jobs struct { type jobs struct {
client *BatchClient client rest.Interface
ns string ns string
} }
// newJobs returns a Jobs // newJobs returns a Jobs
func newJobs(c *BatchClient, namespace string) *jobs { func newJobs(c *BatchClient, namespace string) *jobs {
return &jobs{ return &jobs{
client: c, client: c.RESTClient(),
ns: namespace, ns: namespace,
} }
} }

View File

@ -24,13 +24,13 @@ import (
) )
type CertificatesInterface interface { type CertificatesInterface interface {
GetRESTClient() *rest.RESTClient RESTClient() rest.Interface
CertificateSigningRequestsGetter CertificateSigningRequestsGetter
} }
// CertificatesClient is used to interact with features provided by the Certificates group. // CertificatesClient is used to interact with features provided by the Certificates group.
type CertificatesClient struct { type CertificatesClient struct {
*rest.RESTClient restClient rest.Interface
} }
func (c *CertificatesClient) CertificateSigningRequests() CertificateSigningRequestInterface { func (c *CertificatesClient) CertificateSigningRequests() CertificateSigningRequestInterface {
@ -61,7 +61,7 @@ func NewForConfigOrDie(c *rest.Config) *CertificatesClient {
} }
// New creates a new CertificatesClient for the given RESTClient. // New creates a new CertificatesClient for the given RESTClient.
func New(c *rest.RESTClient) *CertificatesClient { func New(c rest.Interface) *CertificatesClient {
return &CertificatesClient{c} return &CertificatesClient{c}
} }
@ -86,11 +86,11 @@ func setConfigDefaults(config *rest.Config) error {
return nil return nil
} }
// GetRESTClient returns a RESTClient that is used to communicate // RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation. // with API server by this client implementation.
func (c *CertificatesClient) GetRESTClient() *rest.RESTClient { func (c *CertificatesClient) RESTClient() rest.Interface {
if c == nil { if c == nil {
return nil return nil
} }
return c.RESTClient return c.restClient
} }

View File

@ -21,6 +21,7 @@ import (
v1 "k8s.io/client-go/pkg/api/v1" v1 "k8s.io/client-go/pkg/api/v1"
v1alpha1 "k8s.io/client-go/pkg/apis/certificates/v1alpha1" v1alpha1 "k8s.io/client-go/pkg/apis/certificates/v1alpha1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// CertificateSigningRequestsGetter has a method to return a CertificateSigningRequestInterface. // CertificateSigningRequestsGetter has a method to return a CertificateSigningRequestInterface.
@ -45,13 +46,13 @@ type CertificateSigningRequestInterface interface {
// certificateSigningRequests implements CertificateSigningRequestInterface // certificateSigningRequests implements CertificateSigningRequestInterface
type certificateSigningRequests struct { type certificateSigningRequests struct {
client *CertificatesClient client rest.Interface
} }
// newCertificateSigningRequests returns a CertificateSigningRequests // newCertificateSigningRequests returns a CertificateSigningRequests
func newCertificateSigningRequests(c *CertificatesClient) *certificateSigningRequests { func newCertificateSigningRequests(c *CertificatesClient) *certificateSigningRequests {
return &certificateSigningRequests{ return &certificateSigningRequests{
client: c, client: c.RESTClient(),
} }
} }

View File

@ -30,8 +30,9 @@ func (c *FakeCertificates) CertificateSigningRequests() v1alpha1.CertificateSign
return &FakeCertificateSigningRequests{c} return &FakeCertificateSigningRequests{c}
} }
// GetRESTClient returns a RESTClient that is used to communicate // RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation. // with API server by this client implementation.
func (c *FakeCertificates) GetRESTClient() *rest.RESTClient { func (c *FakeCertificates) RESTClient() rest.Interface {
return nil var ret *rest.RESTClient
return ret
} }

View File

@ -20,6 +20,7 @@ import (
api "k8s.io/client-go/pkg/api" api "k8s.io/client-go/pkg/api"
v1 "k8s.io/client-go/pkg/api/v1" v1 "k8s.io/client-go/pkg/api/v1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// ComponentStatusesGetter has a method to return a ComponentStatusInterface. // ComponentStatusesGetter has a method to return a ComponentStatusInterface.
@ -43,13 +44,13 @@ type ComponentStatusInterface interface {
// componentStatuses implements ComponentStatusInterface // componentStatuses implements ComponentStatusInterface
type componentStatuses struct { type componentStatuses struct {
client *CoreClient client rest.Interface
} }
// newComponentStatuses returns a ComponentStatuses // newComponentStatuses returns a ComponentStatuses
func newComponentStatuses(c *CoreClient) *componentStatuses { func newComponentStatuses(c *CoreClient) *componentStatuses {
return &componentStatuses{ return &componentStatuses{
client: c, client: c.RESTClient(),
} }
} }

View File

@ -20,6 +20,7 @@ import (
api "k8s.io/client-go/pkg/api" api "k8s.io/client-go/pkg/api"
v1 "k8s.io/client-go/pkg/api/v1" v1 "k8s.io/client-go/pkg/api/v1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// ConfigMapsGetter has a method to return a ConfigMapInterface. // ConfigMapsGetter has a method to return a ConfigMapInterface.
@ -43,14 +44,14 @@ type ConfigMapInterface interface {
// configMaps implements ConfigMapInterface // configMaps implements ConfigMapInterface
type configMaps struct { type configMaps struct {
client *CoreClient client rest.Interface
ns string ns string
} }
// newConfigMaps returns a ConfigMaps // newConfigMaps returns a ConfigMaps
func newConfigMaps(c *CoreClient, namespace string) *configMaps { func newConfigMaps(c *CoreClient, namespace string) *configMaps {
return &configMaps{ return &configMaps{
client: c, client: c.RESTClient(),
ns: namespace, ns: namespace,
} }
} }

View File

@ -24,7 +24,7 @@ import (
) )
type CoreInterface interface { type CoreInterface interface {
GetRESTClient() *rest.RESTClient RESTClient() rest.Interface
ComponentStatusesGetter ComponentStatusesGetter
ConfigMapsGetter ConfigMapsGetter
EndpointsGetter EndpointsGetter
@ -45,7 +45,7 @@ type CoreInterface interface {
// CoreClient is used to interact with features provided by the Core group. // CoreClient is used to interact with features provided by the Core group.
type CoreClient struct { type CoreClient struct {
*rest.RESTClient restClient rest.Interface
} }
func (c *CoreClient) ComponentStatuses() ComponentStatusInterface { func (c *CoreClient) ComponentStatuses() ComponentStatusInterface {
@ -136,7 +136,7 @@ func NewForConfigOrDie(c *rest.Config) *CoreClient {
} }
// New creates a new CoreClient for the given RESTClient. // New creates a new CoreClient for the given RESTClient.
func New(c *rest.RESTClient) *CoreClient { func New(c rest.Interface) *CoreClient {
return &CoreClient{c} return &CoreClient{c}
} }
@ -161,11 +161,11 @@ func setConfigDefaults(config *rest.Config) error {
return nil return nil
} }
// GetRESTClient returns a RESTClient that is used to communicate // RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation. // with API server by this client implementation.
func (c *CoreClient) GetRESTClient() *rest.RESTClient { func (c *CoreClient) RESTClient() rest.Interface {
if c == nil { if c == nil {
return nil return nil
} }
return c.RESTClient return c.restClient
} }

View File

@ -20,6 +20,7 @@ import (
api "k8s.io/client-go/pkg/api" api "k8s.io/client-go/pkg/api"
v1 "k8s.io/client-go/pkg/api/v1" v1 "k8s.io/client-go/pkg/api/v1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// EndpointsGetter has a method to return a EndpointsInterface. // EndpointsGetter has a method to return a EndpointsInterface.
@ -43,14 +44,14 @@ type EndpointsInterface interface {
// endpoints implements EndpointsInterface // endpoints implements EndpointsInterface
type endpoints struct { type endpoints struct {
client *CoreClient client rest.Interface
ns string ns string
} }
// newEndpoints returns a Endpoints // newEndpoints returns a Endpoints
func newEndpoints(c *CoreClient, namespace string) *endpoints { func newEndpoints(c *CoreClient, namespace string) *endpoints {
return &endpoints{ return &endpoints{
client: c, client: c.RESTClient(),
ns: namespace, ns: namespace,
} }
} }

View File

@ -20,6 +20,7 @@ import (
api "k8s.io/client-go/pkg/api" api "k8s.io/client-go/pkg/api"
v1 "k8s.io/client-go/pkg/api/v1" v1 "k8s.io/client-go/pkg/api/v1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// EventsGetter has a method to return a EventInterface. // EventsGetter has a method to return a EventInterface.
@ -43,14 +44,14 @@ type EventInterface interface {
// events implements EventInterface // events implements EventInterface
type events struct { type events struct {
client *CoreClient client rest.Interface
ns string ns string
} }
// newEvents returns a Events // newEvents returns a Events
func newEvents(c *CoreClient, namespace string) *events { func newEvents(c *CoreClient, namespace string) *events {
return &events{ return &events{
client: c, client: c.RESTClient(),
ns: namespace, ns: namespace,
} }
} }

View File

@ -90,8 +90,9 @@ func (c *FakeCore) ServiceAccounts(namespace string) v1.ServiceAccountInterface
return &FakeServiceAccounts{c, namespace} return &FakeServiceAccounts{c, namespace}
} }
// GetRESTClient returns a RESTClient that is used to communicate // RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation. // with API server by this client implementation.
func (c *FakeCore) GetRESTClient() *rest.RESTClient { func (c *FakeCore) RESTClient() rest.Interface {
return nil var ret *rest.RESTClient
return ret
} }

View File

@ -20,6 +20,7 @@ import (
api "k8s.io/client-go/pkg/api" api "k8s.io/client-go/pkg/api"
v1 "k8s.io/client-go/pkg/api/v1" v1 "k8s.io/client-go/pkg/api/v1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// LimitRangesGetter has a method to return a LimitRangeInterface. // LimitRangesGetter has a method to return a LimitRangeInterface.
@ -43,14 +44,14 @@ type LimitRangeInterface interface {
// limitRanges implements LimitRangeInterface // limitRanges implements LimitRangeInterface
type limitRanges struct { type limitRanges struct {
client *CoreClient client rest.Interface
ns string ns string
} }
// newLimitRanges returns a LimitRanges // newLimitRanges returns a LimitRanges
func newLimitRanges(c *CoreClient, namespace string) *limitRanges { func newLimitRanges(c *CoreClient, namespace string) *limitRanges {
return &limitRanges{ return &limitRanges{
client: c, client: c.RESTClient(),
ns: namespace, ns: namespace,
} }
} }

View File

@ -20,6 +20,7 @@ import (
api "k8s.io/client-go/pkg/api" api "k8s.io/client-go/pkg/api"
v1 "k8s.io/client-go/pkg/api/v1" v1 "k8s.io/client-go/pkg/api/v1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// NamespacesGetter has a method to return a NamespaceInterface. // NamespacesGetter has a method to return a NamespaceInterface.
@ -44,13 +45,13 @@ type NamespaceInterface interface {
// namespaces implements NamespaceInterface // namespaces implements NamespaceInterface
type namespaces struct { type namespaces struct {
client *CoreClient client rest.Interface
} }
// newNamespaces returns a Namespaces // newNamespaces returns a Namespaces
func newNamespaces(c *CoreClient) *namespaces { func newNamespaces(c *CoreClient) *namespaces {
return &namespaces{ return &namespaces{
client: c, client: c.RESTClient(),
} }
} }

View File

@ -20,6 +20,7 @@ import (
api "k8s.io/client-go/pkg/api" api "k8s.io/client-go/pkg/api"
v1 "k8s.io/client-go/pkg/api/v1" v1 "k8s.io/client-go/pkg/api/v1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// NodesGetter has a method to return a NodeInterface. // NodesGetter has a method to return a NodeInterface.
@ -44,13 +45,13 @@ type NodeInterface interface {
// nodes implements NodeInterface // nodes implements NodeInterface
type nodes struct { type nodes struct {
client *CoreClient client rest.Interface
} }
// newNodes returns a Nodes // newNodes returns a Nodes
func newNodes(c *CoreClient) *nodes { func newNodes(c *CoreClient) *nodes {
return &nodes{ return &nodes{
client: c, client: c.RESTClient(),
} }
} }

View File

@ -20,6 +20,7 @@ import (
api "k8s.io/client-go/pkg/api" api "k8s.io/client-go/pkg/api"
v1 "k8s.io/client-go/pkg/api/v1" v1 "k8s.io/client-go/pkg/api/v1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// PersistentVolumesGetter has a method to return a PersistentVolumeInterface. // PersistentVolumesGetter has a method to return a PersistentVolumeInterface.
@ -44,13 +45,13 @@ type PersistentVolumeInterface interface {
// persistentVolumes implements PersistentVolumeInterface // persistentVolumes implements PersistentVolumeInterface
type persistentVolumes struct { type persistentVolumes struct {
client *CoreClient client rest.Interface
} }
// newPersistentVolumes returns a PersistentVolumes // newPersistentVolumes returns a PersistentVolumes
func newPersistentVolumes(c *CoreClient) *persistentVolumes { func newPersistentVolumes(c *CoreClient) *persistentVolumes {
return &persistentVolumes{ return &persistentVolumes{
client: c, client: c.RESTClient(),
} }
} }

View File

@ -20,6 +20,7 @@ import (
api "k8s.io/client-go/pkg/api" api "k8s.io/client-go/pkg/api"
v1 "k8s.io/client-go/pkg/api/v1" v1 "k8s.io/client-go/pkg/api/v1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// PersistentVolumeClaimsGetter has a method to return a PersistentVolumeClaimInterface. // PersistentVolumeClaimsGetter has a method to return a PersistentVolumeClaimInterface.
@ -44,14 +45,14 @@ type PersistentVolumeClaimInterface interface {
// persistentVolumeClaims implements PersistentVolumeClaimInterface // persistentVolumeClaims implements PersistentVolumeClaimInterface
type persistentVolumeClaims struct { type persistentVolumeClaims struct {
client *CoreClient client rest.Interface
ns string ns string
} }
// newPersistentVolumeClaims returns a PersistentVolumeClaims // newPersistentVolumeClaims returns a PersistentVolumeClaims
func newPersistentVolumeClaims(c *CoreClient, namespace string) *persistentVolumeClaims { func newPersistentVolumeClaims(c *CoreClient, namespace string) *persistentVolumeClaims {
return &persistentVolumeClaims{ return &persistentVolumeClaims{
client: c, client: c.RESTClient(),
ns: namespace, ns: namespace,
} }
} }

View File

@ -20,6 +20,7 @@ import (
api "k8s.io/client-go/pkg/api" api "k8s.io/client-go/pkg/api"
v1 "k8s.io/client-go/pkg/api/v1" v1 "k8s.io/client-go/pkg/api/v1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// PodsGetter has a method to return a PodInterface. // PodsGetter has a method to return a PodInterface.
@ -44,14 +45,14 @@ type PodInterface interface {
// pods implements PodInterface // pods implements PodInterface
type pods struct { type pods struct {
client *CoreClient client rest.Interface
ns string ns string
} }
// newPods returns a Pods // newPods returns a Pods
func newPods(c *CoreClient, namespace string) *pods { func newPods(c *CoreClient, namespace string) *pods {
return &pods{ return &pods{
client: c, client: c.RESTClient(),
ns: namespace, ns: namespace,
} }
} }

View File

@ -20,6 +20,7 @@ import (
api "k8s.io/client-go/pkg/api" api "k8s.io/client-go/pkg/api"
v1 "k8s.io/client-go/pkg/api/v1" v1 "k8s.io/client-go/pkg/api/v1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// PodTemplatesGetter has a method to return a PodTemplateInterface. // PodTemplatesGetter has a method to return a PodTemplateInterface.
@ -43,14 +44,14 @@ type PodTemplateInterface interface {
// podTemplates implements PodTemplateInterface // podTemplates implements PodTemplateInterface
type podTemplates struct { type podTemplates struct {
client *CoreClient client rest.Interface
ns string ns string
} }
// newPodTemplates returns a PodTemplates // newPodTemplates returns a PodTemplates
func newPodTemplates(c *CoreClient, namespace string) *podTemplates { func newPodTemplates(c *CoreClient, namespace string) *podTemplates {
return &podTemplates{ return &podTemplates{
client: c, client: c.RESTClient(),
ns: namespace, ns: namespace,
} }
} }

View File

@ -20,6 +20,7 @@ import (
api "k8s.io/client-go/pkg/api" api "k8s.io/client-go/pkg/api"
v1 "k8s.io/client-go/pkg/api/v1" v1 "k8s.io/client-go/pkg/api/v1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// ReplicationControllersGetter has a method to return a ReplicationControllerInterface. // ReplicationControllersGetter has a method to return a ReplicationControllerInterface.
@ -44,14 +45,14 @@ type ReplicationControllerInterface interface {
// replicationControllers implements ReplicationControllerInterface // replicationControllers implements ReplicationControllerInterface
type replicationControllers struct { type replicationControllers struct {
client *CoreClient client rest.Interface
ns string ns string
} }
// newReplicationControllers returns a ReplicationControllers // newReplicationControllers returns a ReplicationControllers
func newReplicationControllers(c *CoreClient, namespace string) *replicationControllers { func newReplicationControllers(c *CoreClient, namespace string) *replicationControllers {
return &replicationControllers{ return &replicationControllers{
client: c, client: c.RESTClient(),
ns: namespace, ns: namespace,
} }
} }

View File

@ -20,6 +20,7 @@ import (
api "k8s.io/client-go/pkg/api" api "k8s.io/client-go/pkg/api"
v1 "k8s.io/client-go/pkg/api/v1" v1 "k8s.io/client-go/pkg/api/v1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// ResourceQuotasGetter has a method to return a ResourceQuotaInterface. // ResourceQuotasGetter has a method to return a ResourceQuotaInterface.
@ -44,14 +45,14 @@ type ResourceQuotaInterface interface {
// resourceQuotas implements ResourceQuotaInterface // resourceQuotas implements ResourceQuotaInterface
type resourceQuotas struct { type resourceQuotas struct {
client *CoreClient client rest.Interface
ns string ns string
} }
// newResourceQuotas returns a ResourceQuotas // newResourceQuotas returns a ResourceQuotas
func newResourceQuotas(c *CoreClient, namespace string) *resourceQuotas { func newResourceQuotas(c *CoreClient, namespace string) *resourceQuotas {
return &resourceQuotas{ return &resourceQuotas{
client: c, client: c.RESTClient(),
ns: namespace, ns: namespace,
} }
} }

View File

@ -20,6 +20,7 @@ import (
api "k8s.io/client-go/pkg/api" api "k8s.io/client-go/pkg/api"
v1 "k8s.io/client-go/pkg/api/v1" v1 "k8s.io/client-go/pkg/api/v1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// SecretsGetter has a method to return a SecretInterface. // SecretsGetter has a method to return a SecretInterface.
@ -43,14 +44,14 @@ type SecretInterface interface {
// secrets implements SecretInterface // secrets implements SecretInterface
type secrets struct { type secrets struct {
client *CoreClient client rest.Interface
ns string ns string
} }
// newSecrets returns a Secrets // newSecrets returns a Secrets
func newSecrets(c *CoreClient, namespace string) *secrets { func newSecrets(c *CoreClient, namespace string) *secrets {
return &secrets{ return &secrets{
client: c, client: c.RESTClient(),
ns: namespace, ns: namespace,
} }
} }

View File

@ -20,6 +20,7 @@ import (
api "k8s.io/client-go/pkg/api" api "k8s.io/client-go/pkg/api"
v1 "k8s.io/client-go/pkg/api/v1" v1 "k8s.io/client-go/pkg/api/v1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// ServicesGetter has a method to return a ServiceInterface. // ServicesGetter has a method to return a ServiceInterface.
@ -44,14 +45,14 @@ type ServiceInterface interface {
// services implements ServiceInterface // services implements ServiceInterface
type services struct { type services struct {
client *CoreClient client rest.Interface
ns string ns string
} }
// newServices returns a Services // newServices returns a Services
func newServices(c *CoreClient, namespace string) *services { func newServices(c *CoreClient, namespace string) *services {
return &services{ return &services{
client: c, client: c.RESTClient(),
ns: namespace, ns: namespace,
} }
} }

View File

@ -20,6 +20,7 @@ import (
api "k8s.io/client-go/pkg/api" api "k8s.io/client-go/pkg/api"
v1 "k8s.io/client-go/pkg/api/v1" v1 "k8s.io/client-go/pkg/api/v1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// ServiceAccountsGetter has a method to return a ServiceAccountInterface. // ServiceAccountsGetter has a method to return a ServiceAccountInterface.
@ -43,14 +44,14 @@ type ServiceAccountInterface interface {
// serviceAccounts implements ServiceAccountInterface // serviceAccounts implements ServiceAccountInterface
type serviceAccounts struct { type serviceAccounts struct {
client *CoreClient client rest.Interface
ns string ns string
} }
// newServiceAccounts returns a ServiceAccounts // newServiceAccounts returns a ServiceAccounts
func newServiceAccounts(c *CoreClient, namespace string) *serviceAccounts { func newServiceAccounts(c *CoreClient, namespace string) *serviceAccounts {
return &serviceAccounts{ return &serviceAccounts{
client: c, client: c.RESTClient(),
ns: namespace, ns: namespace,
} }
} }

View File

@ -21,6 +21,7 @@ import (
v1 "k8s.io/client-go/pkg/api/v1" v1 "k8s.io/client-go/pkg/api/v1"
v1beta1 "k8s.io/client-go/pkg/apis/extensions/v1beta1" v1beta1 "k8s.io/client-go/pkg/apis/extensions/v1beta1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// DaemonSetsGetter has a method to return a DaemonSetInterface. // DaemonSetsGetter has a method to return a DaemonSetInterface.
@ -45,14 +46,14 @@ type DaemonSetInterface interface {
// daemonSets implements DaemonSetInterface // daemonSets implements DaemonSetInterface
type daemonSets struct { type daemonSets struct {
client *ExtensionsClient client rest.Interface
ns string ns string
} }
// newDaemonSets returns a DaemonSets // newDaemonSets returns a DaemonSets
func newDaemonSets(c *ExtensionsClient, namespace string) *daemonSets { func newDaemonSets(c *ExtensionsClient, namespace string) *daemonSets {
return &daemonSets{ return &daemonSets{
client: c, client: c.RESTClient(),
ns: namespace, ns: namespace,
} }
} }

View File

@ -21,6 +21,7 @@ import (
v1 "k8s.io/client-go/pkg/api/v1" v1 "k8s.io/client-go/pkg/api/v1"
v1beta1 "k8s.io/client-go/pkg/apis/extensions/v1beta1" v1beta1 "k8s.io/client-go/pkg/apis/extensions/v1beta1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// DeploymentsGetter has a method to return a DeploymentInterface. // DeploymentsGetter has a method to return a DeploymentInterface.
@ -45,14 +46,14 @@ type DeploymentInterface interface {
// deployments implements DeploymentInterface // deployments implements DeploymentInterface
type deployments struct { type deployments struct {
client *ExtensionsClient client rest.Interface
ns string ns string
} }
// newDeployments returns a Deployments // newDeployments returns a Deployments
func newDeployments(c *ExtensionsClient, namespace string) *deployments { func newDeployments(c *ExtensionsClient, namespace string) *deployments {
return &deployments{ return &deployments{
client: c, client: c.RESTClient(),
ns: namespace, ns: namespace,
} }
} }

View File

@ -24,7 +24,7 @@ import (
) )
type ExtensionsInterface interface { type ExtensionsInterface interface {
GetRESTClient() *rest.RESTClient RESTClient() rest.Interface
DaemonSetsGetter DaemonSetsGetter
DeploymentsGetter DeploymentsGetter
IngressesGetter IngressesGetter
@ -37,7 +37,7 @@ type ExtensionsInterface interface {
// ExtensionsClient is used to interact with features provided by the Extensions group. // ExtensionsClient is used to interact with features provided by the Extensions group.
type ExtensionsClient struct { type ExtensionsClient struct {
*rest.RESTClient restClient rest.Interface
} }
func (c *ExtensionsClient) DaemonSets(namespace string) DaemonSetInterface { func (c *ExtensionsClient) DaemonSets(namespace string) DaemonSetInterface {
@ -96,7 +96,7 @@ func NewForConfigOrDie(c *rest.Config) *ExtensionsClient {
} }
// New creates a new ExtensionsClient for the given RESTClient. // New creates a new ExtensionsClient for the given RESTClient.
func New(c *rest.RESTClient) *ExtensionsClient { func New(c rest.Interface) *ExtensionsClient {
return &ExtensionsClient{c} return &ExtensionsClient{c}
} }
@ -121,11 +121,11 @@ func setConfigDefaults(config *rest.Config) error {
return nil return nil
} }
// GetRESTClient returns a RESTClient that is used to communicate // RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation. // with API server by this client implementation.
func (c *ExtensionsClient) GetRESTClient() *rest.RESTClient { func (c *ExtensionsClient) RESTClient() rest.Interface {
if c == nil { if c == nil {
return nil return nil
} }
return c.RESTClient return c.restClient
} }

View File

@ -58,8 +58,9 @@ func (c *FakeExtensions) ThirdPartyResources() v1beta1.ThirdPartyResourceInterfa
return &FakeThirdPartyResources{c} return &FakeThirdPartyResources{c}
} }
// GetRESTClient returns a RESTClient that is used to communicate // RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation. // with API server by this client implementation.
func (c *FakeExtensions) GetRESTClient() *rest.RESTClient { func (c *FakeExtensions) RESTClient() rest.Interface {
return nil var ret *rest.RESTClient
return ret
} }

View File

@ -21,6 +21,7 @@ import (
v1 "k8s.io/client-go/pkg/api/v1" v1 "k8s.io/client-go/pkg/api/v1"
v1beta1 "k8s.io/client-go/pkg/apis/extensions/v1beta1" v1beta1 "k8s.io/client-go/pkg/apis/extensions/v1beta1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// IngressesGetter has a method to return a IngressInterface. // IngressesGetter has a method to return a IngressInterface.
@ -45,14 +46,14 @@ type IngressInterface interface {
// ingresses implements IngressInterface // ingresses implements IngressInterface
type ingresses struct { type ingresses struct {
client *ExtensionsClient client rest.Interface
ns string ns string
} }
// newIngresses returns a Ingresses // newIngresses returns a Ingresses
func newIngresses(c *ExtensionsClient, namespace string) *ingresses { func newIngresses(c *ExtensionsClient, namespace string) *ingresses {
return &ingresses{ return &ingresses{
client: c, client: c.RESTClient(),
ns: namespace, ns: namespace,
} }
} }

View File

@ -21,6 +21,7 @@ import (
v1 "k8s.io/client-go/pkg/api/v1" v1 "k8s.io/client-go/pkg/api/v1"
v1beta1 "k8s.io/client-go/pkg/apis/extensions/v1beta1" v1beta1 "k8s.io/client-go/pkg/apis/extensions/v1beta1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// JobsGetter has a method to return a JobInterface. // JobsGetter has a method to return a JobInterface.
@ -45,14 +46,14 @@ type JobInterface interface {
// jobs implements JobInterface // jobs implements JobInterface
type jobs struct { type jobs struct {
client *ExtensionsClient client rest.Interface
ns string ns string
} }
// newJobs returns a Jobs // newJobs returns a Jobs
func newJobs(c *ExtensionsClient, namespace string) *jobs { func newJobs(c *ExtensionsClient, namespace string) *jobs {
return &jobs{ return &jobs{
client: c, client: c.RESTClient(),
ns: namespace, ns: namespace,
} }
} }

View File

@ -21,6 +21,7 @@ import (
v1 "k8s.io/client-go/pkg/api/v1" v1 "k8s.io/client-go/pkg/api/v1"
v1beta1 "k8s.io/client-go/pkg/apis/extensions/v1beta1" v1beta1 "k8s.io/client-go/pkg/apis/extensions/v1beta1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// PodSecurityPoliciesGetter has a method to return a PodSecurityPolicyInterface. // PodSecurityPoliciesGetter has a method to return a PodSecurityPolicyInterface.
@ -44,13 +45,13 @@ type PodSecurityPolicyInterface interface {
// podSecurityPolicies implements PodSecurityPolicyInterface // podSecurityPolicies implements PodSecurityPolicyInterface
type podSecurityPolicies struct { type podSecurityPolicies struct {
client *ExtensionsClient client rest.Interface
} }
// newPodSecurityPolicies returns a PodSecurityPolicies // newPodSecurityPolicies returns a PodSecurityPolicies
func newPodSecurityPolicies(c *ExtensionsClient) *podSecurityPolicies { func newPodSecurityPolicies(c *ExtensionsClient) *podSecurityPolicies {
return &podSecurityPolicies{ return &podSecurityPolicies{
client: c, client: c.RESTClient(),
} }
} }

View File

@ -21,6 +21,7 @@ import (
v1 "k8s.io/client-go/pkg/api/v1" v1 "k8s.io/client-go/pkg/api/v1"
v1beta1 "k8s.io/client-go/pkg/apis/extensions/v1beta1" v1beta1 "k8s.io/client-go/pkg/apis/extensions/v1beta1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// ReplicaSetsGetter has a method to return a ReplicaSetInterface. // ReplicaSetsGetter has a method to return a ReplicaSetInterface.
@ -45,14 +46,14 @@ type ReplicaSetInterface interface {
// replicaSets implements ReplicaSetInterface // replicaSets implements ReplicaSetInterface
type replicaSets struct { type replicaSets struct {
client *ExtensionsClient client rest.Interface
ns string ns string
} }
// newReplicaSets returns a ReplicaSets // newReplicaSets returns a ReplicaSets
func newReplicaSets(c *ExtensionsClient, namespace string) *replicaSets { func newReplicaSets(c *ExtensionsClient, namespace string) *replicaSets {
return &replicaSets{ return &replicaSets{
client: c, client: c.RESTClient(),
ns: namespace, ns: namespace,
} }
} }

View File

@ -16,6 +16,10 @@ limitations under the License.
package v1beta1 package v1beta1
import (
rest "k8s.io/client-go/rest"
)
// ScalesGetter has a method to return a ScaleInterface. // ScalesGetter has a method to return a ScaleInterface.
// A group's client should implement this interface. // A group's client should implement this interface.
type ScalesGetter interface { type ScalesGetter interface {
@ -29,14 +33,14 @@ type ScaleInterface interface {
// scales implements ScaleInterface // scales implements ScaleInterface
type scales struct { type scales struct {
client *ExtensionsClient client rest.Interface
ns string ns string
} }
// newScales returns a Scales // newScales returns a Scales
func newScales(c *ExtensionsClient, namespace string) *scales { func newScales(c *ExtensionsClient, namespace string) *scales {
return &scales{ return &scales{
client: c, client: c.RESTClient(),
ns: namespace, ns: namespace,
} }
} }

View File

@ -21,6 +21,7 @@ import (
v1 "k8s.io/client-go/pkg/api/v1" v1 "k8s.io/client-go/pkg/api/v1"
v1beta1 "k8s.io/client-go/pkg/apis/extensions/v1beta1" v1beta1 "k8s.io/client-go/pkg/apis/extensions/v1beta1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// ThirdPartyResourcesGetter has a method to return a ThirdPartyResourceInterface. // ThirdPartyResourcesGetter has a method to return a ThirdPartyResourceInterface.
@ -44,13 +45,13 @@ type ThirdPartyResourceInterface interface {
// thirdPartyResources implements ThirdPartyResourceInterface // thirdPartyResources implements ThirdPartyResourceInterface
type thirdPartyResources struct { type thirdPartyResources struct {
client *ExtensionsClient client rest.Interface
} }
// newThirdPartyResources returns a ThirdPartyResources // newThirdPartyResources returns a ThirdPartyResources
func newThirdPartyResources(c *ExtensionsClient) *thirdPartyResources { func newThirdPartyResources(c *ExtensionsClient) *thirdPartyResources {
return &thirdPartyResources{ return &thirdPartyResources{
client: c, client: c.RESTClient(),
} }
} }

View File

@ -30,8 +30,9 @@ func (c *FakePolicy) PodDisruptionBudgets(namespace string) v1alpha1.PodDisrupti
return &FakePodDisruptionBudgets{c, namespace} return &FakePodDisruptionBudgets{c, namespace}
} }
// GetRESTClient returns a RESTClient that is used to communicate // RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation. // with API server by this client implementation.
func (c *FakePolicy) GetRESTClient() *rest.RESTClient { func (c *FakePolicy) RESTClient() rest.Interface {
return nil var ret *rest.RESTClient
return ret
} }

View File

@ -21,6 +21,7 @@ import (
v1 "k8s.io/client-go/pkg/api/v1" v1 "k8s.io/client-go/pkg/api/v1"
v1alpha1 "k8s.io/client-go/pkg/apis/policy/v1alpha1" v1alpha1 "k8s.io/client-go/pkg/apis/policy/v1alpha1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// PodDisruptionBudgetsGetter has a method to return a PodDisruptionBudgetInterface. // PodDisruptionBudgetsGetter has a method to return a PodDisruptionBudgetInterface.
@ -45,14 +46,14 @@ type PodDisruptionBudgetInterface interface {
// podDisruptionBudgets implements PodDisruptionBudgetInterface // podDisruptionBudgets implements PodDisruptionBudgetInterface
type podDisruptionBudgets struct { type podDisruptionBudgets struct {
client *PolicyClient client rest.Interface
ns string ns string
} }
// newPodDisruptionBudgets returns a PodDisruptionBudgets // newPodDisruptionBudgets returns a PodDisruptionBudgets
func newPodDisruptionBudgets(c *PolicyClient, namespace string) *podDisruptionBudgets { func newPodDisruptionBudgets(c *PolicyClient, namespace string) *podDisruptionBudgets {
return &podDisruptionBudgets{ return &podDisruptionBudgets{
client: c, client: c.RESTClient(),
ns: namespace, ns: namespace,
} }
} }

View File

@ -24,13 +24,13 @@ import (
) )
type PolicyInterface interface { type PolicyInterface interface {
GetRESTClient() *rest.RESTClient RESTClient() rest.Interface
PodDisruptionBudgetsGetter PodDisruptionBudgetsGetter
} }
// PolicyClient is used to interact with features provided by the Policy group. // PolicyClient is used to interact with features provided by the Policy group.
type PolicyClient struct { type PolicyClient struct {
*rest.RESTClient restClient rest.Interface
} }
func (c *PolicyClient) PodDisruptionBudgets(namespace string) PodDisruptionBudgetInterface { func (c *PolicyClient) PodDisruptionBudgets(namespace string) PodDisruptionBudgetInterface {
@ -61,7 +61,7 @@ func NewForConfigOrDie(c *rest.Config) *PolicyClient {
} }
// New creates a new PolicyClient for the given RESTClient. // New creates a new PolicyClient for the given RESTClient.
func New(c *rest.RESTClient) *PolicyClient { func New(c rest.Interface) *PolicyClient {
return &PolicyClient{c} return &PolicyClient{c}
} }
@ -86,11 +86,11 @@ func setConfigDefaults(config *rest.Config) error {
return nil return nil
} }
// GetRESTClient returns a RESTClient that is used to communicate // RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation. // with API server by this client implementation.
func (c *PolicyClient) GetRESTClient() *rest.RESTClient { func (c *PolicyClient) RESTClient() rest.Interface {
if c == nil { if c == nil {
return nil return nil
} }
return c.RESTClient return c.restClient
} }

View File

@ -21,6 +21,7 @@ import (
v1 "k8s.io/client-go/pkg/api/v1" v1 "k8s.io/client-go/pkg/api/v1"
v1alpha1 "k8s.io/client-go/pkg/apis/rbac/v1alpha1" v1alpha1 "k8s.io/client-go/pkg/apis/rbac/v1alpha1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// ClusterRolesGetter has a method to return a ClusterRoleInterface. // ClusterRolesGetter has a method to return a ClusterRoleInterface.
@ -44,13 +45,13 @@ type ClusterRoleInterface interface {
// clusterRoles implements ClusterRoleInterface // clusterRoles implements ClusterRoleInterface
type clusterRoles struct { type clusterRoles struct {
client *RbacClient client rest.Interface
} }
// newClusterRoles returns a ClusterRoles // newClusterRoles returns a ClusterRoles
func newClusterRoles(c *RbacClient) *clusterRoles { func newClusterRoles(c *RbacClient) *clusterRoles {
return &clusterRoles{ return &clusterRoles{
client: c, client: c.RESTClient(),
} }
} }

View File

@ -21,6 +21,7 @@ import (
v1 "k8s.io/client-go/pkg/api/v1" v1 "k8s.io/client-go/pkg/api/v1"
v1alpha1 "k8s.io/client-go/pkg/apis/rbac/v1alpha1" v1alpha1 "k8s.io/client-go/pkg/apis/rbac/v1alpha1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// ClusterRoleBindingsGetter has a method to return a ClusterRoleBindingInterface. // ClusterRoleBindingsGetter has a method to return a ClusterRoleBindingInterface.
@ -44,13 +45,13 @@ type ClusterRoleBindingInterface interface {
// clusterRoleBindings implements ClusterRoleBindingInterface // clusterRoleBindings implements ClusterRoleBindingInterface
type clusterRoleBindings struct { type clusterRoleBindings struct {
client *RbacClient client rest.Interface
} }
// newClusterRoleBindings returns a ClusterRoleBindings // newClusterRoleBindings returns a ClusterRoleBindings
func newClusterRoleBindings(c *RbacClient) *clusterRoleBindings { func newClusterRoleBindings(c *RbacClient) *clusterRoleBindings {
return &clusterRoleBindings{ return &clusterRoleBindings{
client: c, client: c.RESTClient(),
} }
} }

View File

@ -42,8 +42,9 @@ func (c *FakeRbac) RoleBindings(namespace string) v1alpha1.RoleBindingInterface
return &FakeRoleBindings{c, namespace} return &FakeRoleBindings{c, namespace}
} }
// GetRESTClient returns a RESTClient that is used to communicate // RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation. // with API server by this client implementation.
func (c *FakeRbac) GetRESTClient() *rest.RESTClient { func (c *FakeRbac) RESTClient() rest.Interface {
return nil var ret *rest.RESTClient
return ret
} }

View File

@ -24,7 +24,7 @@ import (
) )
type RbacInterface interface { type RbacInterface interface {
GetRESTClient() *rest.RESTClient RESTClient() rest.Interface
ClusterRolesGetter ClusterRolesGetter
ClusterRoleBindingsGetter ClusterRoleBindingsGetter
RolesGetter RolesGetter
@ -33,7 +33,7 @@ type RbacInterface interface {
// RbacClient is used to interact with features provided by the Rbac group. // RbacClient is used to interact with features provided by the Rbac group.
type RbacClient struct { type RbacClient struct {
*rest.RESTClient restClient rest.Interface
} }
func (c *RbacClient) ClusterRoles() ClusterRoleInterface { func (c *RbacClient) ClusterRoles() ClusterRoleInterface {
@ -76,7 +76,7 @@ func NewForConfigOrDie(c *rest.Config) *RbacClient {
} }
// New creates a new RbacClient for the given RESTClient. // New creates a new RbacClient for the given RESTClient.
func New(c *rest.RESTClient) *RbacClient { func New(c rest.Interface) *RbacClient {
return &RbacClient{c} return &RbacClient{c}
} }
@ -101,11 +101,11 @@ func setConfigDefaults(config *rest.Config) error {
return nil return nil
} }
// GetRESTClient returns a RESTClient that is used to communicate // RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation. // with API server by this client implementation.
func (c *RbacClient) GetRESTClient() *rest.RESTClient { func (c *RbacClient) RESTClient() rest.Interface {
if c == nil { if c == nil {
return nil return nil
} }
return c.RESTClient return c.restClient
} }

View File

@ -21,6 +21,7 @@ import (
v1 "k8s.io/client-go/pkg/api/v1" v1 "k8s.io/client-go/pkg/api/v1"
v1alpha1 "k8s.io/client-go/pkg/apis/rbac/v1alpha1" v1alpha1 "k8s.io/client-go/pkg/apis/rbac/v1alpha1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// RolesGetter has a method to return a RoleInterface. // RolesGetter has a method to return a RoleInterface.
@ -44,14 +45,14 @@ type RoleInterface interface {
// roles implements RoleInterface // roles implements RoleInterface
type roles struct { type roles struct {
client *RbacClient client rest.Interface
ns string ns string
} }
// newRoles returns a Roles // newRoles returns a Roles
func newRoles(c *RbacClient, namespace string) *roles { func newRoles(c *RbacClient, namespace string) *roles {
return &roles{ return &roles{
client: c, client: c.RESTClient(),
ns: namespace, ns: namespace,
} }
} }

View File

@ -21,6 +21,7 @@ import (
v1 "k8s.io/client-go/pkg/api/v1" v1 "k8s.io/client-go/pkg/api/v1"
v1alpha1 "k8s.io/client-go/pkg/apis/rbac/v1alpha1" v1alpha1 "k8s.io/client-go/pkg/apis/rbac/v1alpha1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// RoleBindingsGetter has a method to return a RoleBindingInterface. // RoleBindingsGetter has a method to return a RoleBindingInterface.
@ -44,14 +45,14 @@ type RoleBindingInterface interface {
// roleBindings implements RoleBindingInterface // roleBindings implements RoleBindingInterface
type roleBindings struct { type roleBindings struct {
client *RbacClient client rest.Interface
ns string ns string
} }
// newRoleBindings returns a RoleBindings // newRoleBindings returns a RoleBindings
func newRoleBindings(c *RbacClient, namespace string) *roleBindings { func newRoleBindings(c *RbacClient, namespace string) *roleBindings {
return &roleBindings{ return &roleBindings{
client: c, client: c.RESTClient(),
ns: namespace, ns: namespace,
} }
} }

View File

@ -30,8 +30,9 @@ func (c *FakeStorage) StorageClasses() v1beta1.StorageClassInterface {
return &FakeStorageClasses{c} return &FakeStorageClasses{c}
} }
// GetRESTClient returns a RESTClient that is used to communicate // RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation. // with API server by this client implementation.
func (c *FakeStorage) GetRESTClient() *rest.RESTClient { func (c *FakeStorage) RESTClient() rest.Interface {
return nil var ret *rest.RESTClient
return ret
} }

View File

@ -24,13 +24,13 @@ import (
) )
type StorageInterface interface { type StorageInterface interface {
GetRESTClient() *rest.RESTClient RESTClient() rest.Interface
StorageClassesGetter StorageClassesGetter
} }
// StorageClient is used to interact with features provided by the Storage group. // StorageClient is used to interact with features provided by the Storage group.
type StorageClient struct { type StorageClient struct {
*rest.RESTClient restClient rest.Interface
} }
func (c *StorageClient) StorageClasses() StorageClassInterface { func (c *StorageClient) StorageClasses() StorageClassInterface {
@ -61,7 +61,7 @@ func NewForConfigOrDie(c *rest.Config) *StorageClient {
} }
// New creates a new StorageClient for the given RESTClient. // New creates a new StorageClient for the given RESTClient.
func New(c *rest.RESTClient) *StorageClient { func New(c rest.Interface) *StorageClient {
return &StorageClient{c} return &StorageClient{c}
} }
@ -86,11 +86,11 @@ func setConfigDefaults(config *rest.Config) error {
return nil return nil
} }
// GetRESTClient returns a RESTClient that is used to communicate // RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation. // with API server by this client implementation.
func (c *StorageClient) GetRESTClient() *rest.RESTClient { func (c *StorageClient) RESTClient() rest.Interface {
if c == nil { if c == nil {
return nil return nil
} }
return c.RESTClient return c.restClient
} }

View File

@ -21,6 +21,7 @@ import (
v1 "k8s.io/client-go/pkg/api/v1" v1 "k8s.io/client-go/pkg/api/v1"
v1beta1 "k8s.io/client-go/pkg/apis/storage/v1beta1" v1beta1 "k8s.io/client-go/pkg/apis/storage/v1beta1"
watch "k8s.io/client-go/pkg/watch" watch "k8s.io/client-go/pkg/watch"
rest "k8s.io/client-go/rest"
) )
// StorageClassesGetter has a method to return a StorageClassInterface. // StorageClassesGetter has a method to return a StorageClassInterface.
@ -44,13 +45,13 @@ type StorageClassInterface interface {
// storageClasses implements StorageClassInterface // storageClasses implements StorageClassInterface
type storageClasses struct { type storageClasses struct {
client *StorageClient client rest.Interface
} }
// newStorageClasses returns a StorageClasses // newStorageClasses returns a StorageClasses
func newStorageClasses(c *StorageClient) *storageClasses { func newStorageClasses(c *StorageClient) *storageClasses {
return &storageClasses{ return &storageClasses{
client: c, client: c.RESTClient(),
} }
} }

View File

@ -153,6 +153,7 @@ func Convert_bool_To_Pointer_bool(in *bool, out **bool, s conversion.Scope) erro
return nil return nil
} }
// +k8s:conversion-fn=drop
func Convert_unversioned_TypeMeta_To_unversioned_TypeMeta(in, out *unversioned.TypeMeta, s conversion.Scope) error { func Convert_unversioned_TypeMeta_To_unversioned_TypeMeta(in, out *unversioned.TypeMeta, s conversion.Scope) error {
// These values are explicitly not copied // These values are explicitly not copied
//out.APIVersion = in.APIVersion //out.APIVersion = in.APIVersion
@ -160,16 +161,19 @@ func Convert_unversioned_TypeMeta_To_unversioned_TypeMeta(in, out *unversioned.T
return nil return nil
} }
// +k8s:conversion-fn=copy-only
func Convert_unversioned_ListMeta_To_unversioned_ListMeta(in, out *unversioned.ListMeta, s conversion.Scope) error { func Convert_unversioned_ListMeta_To_unversioned_ListMeta(in, out *unversioned.ListMeta, s conversion.Scope) error {
*out = *in *out = *in
return nil return nil
} }
// +k8s:conversion-fn=copy-only
func Convert_intstr_IntOrString_To_intstr_IntOrString(in, out *intstr.IntOrString, s conversion.Scope) error { func Convert_intstr_IntOrString_To_intstr_IntOrString(in, out *intstr.IntOrString, s conversion.Scope) error {
*out = *in *out = *in
return nil return nil
} }
// +k8s:conversion-fn=copy-only
func Convert_unversioned_Time_To_unversioned_Time(in *unversioned.Time, out *unversioned.Time, s conversion.Scope) error { func Convert_unversioned_Time_To_unversioned_Time(in *unversioned.Time, out *unversioned.Time, s conversion.Scope) error {
// Cannot deep copy these, because time.Time has unexported fields. // Cannot deep copy these, because time.Time has unexported fields.
*out = *in *out = *in
@ -219,6 +223,7 @@ func Convert_fields_Selector_To_string(in *fields.Selector, out *string, s conve
return nil return nil
} }
// +k8s:conversion-fn=copy-only
func Convert_resource_Quantity_To_resource_Quantity(in *resource.Quantity, out *resource.Quantity, s conversion.Scope) error { func Convert_resource_Quantity_To_resource_Quantity(in *resource.Quantity, out *resource.Quantity, s conversion.Scope) error {
*out = *in *out = *in
return nil return nil

View File

@ -120,6 +120,22 @@ func IsStandardContainerResourceName(str string) bool {
return standardContainerResources.Has(str) return standardContainerResources.Has(str)
} }
// IsOpaqueIntResourceName returns true if the resource name has the opaque
// integer resource prefix.
func IsOpaqueIntResourceName(name ResourceName) bool {
return strings.HasPrefix(string(name), ResourceOpaqueIntPrefix)
}
// OpaqueIntResourceName returns a ResourceName with the canonical opaque
// integer prefix prepended. If the argument already has the prefix, it is
// returned unmodified.
func OpaqueIntResourceName(name string) ResourceName {
if IsOpaqueIntResourceName(ResourceName(name)) {
return ResourceName(name)
}
return ResourceName(fmt.Sprintf("%s%s", ResourceOpaqueIntPrefix, name))
}
var standardLimitRangeTypes = sets.NewString( var standardLimitRangeTypes = sets.NewString(
string(LimitTypePod), string(LimitTypePod),
string(LimitTypeContainer), string(LimitTypeContainer),
@ -171,6 +187,7 @@ var standardResources = sets.NewString(
string(ResourceConfigMaps), string(ResourceConfigMaps),
string(ResourcePersistentVolumeClaims), string(ResourcePersistentVolumeClaims),
string(ResourceStorage), string(ResourceStorage),
string(ResourceRequestsStorage),
) )
// IsStandardResourceName returns true if the resource is known to the system // IsStandardResourceName returns true if the resource is known to the system
@ -192,7 +209,7 @@ var integerResources = sets.NewString(
// IsIntegerResourceName returns true if the resource is measured in integer values // IsIntegerResourceName returns true if the resource is measured in integer values
func IsIntegerResourceName(str string) bool { func IsIntegerResourceName(str string) bool {
return integerResources.Has(str) return integerResources.Has(str) || IsOpaqueIntResourceName(ResourceName(str))
} }
// NewDeleteOptions returns a DeleteOptions indicating the resource should // NewDeleteOptions returns a DeleteOptions indicating the resource should
@ -236,6 +253,20 @@ var standardFinalizers = sets.NewString(
FinalizerOrphan, FinalizerOrphan,
) )
// HasAnnotation returns a bool if passed in annotation exists
func HasAnnotation(obj ObjectMeta, ann string) bool {
_, found := obj.Annotations[ann]
return found
}
// SetMetaDataAnnotation sets the annotation and value
func SetMetaDataAnnotation(obj *ObjectMeta, ann string, value string) {
if obj.Annotations == nil {
obj.Annotations = make(map[string]string)
}
obj.Annotations[ann] = value
}
func IsStandardFinalizerName(str string) bool { func IsStandardFinalizerName(str string) bool {
return standardFinalizers.Has(str) return standardFinalizers.Has(str)
} }
@ -402,7 +433,7 @@ func NodeSelectorRequirementsAsSelector(nsm []NodeSelectorRequirement) (labels.S
default: default:
return nil, fmt.Errorf("%q is not a valid node selector operator", expr.Operator) return nil, fmt.Errorf("%q is not a valid node selector operator", expr.Operator)
} }
r, err := labels.NewRequirement(expr.Key, op, sets.NewString(expr.Values...)) r, err := labels.NewRequirement(expr.Key, op, expr.Values)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -512,7 +543,6 @@ func TolerationToleratesTaint(toleration *Toleration, taint *Taint) bool {
return true return true
} }
return false return false
} }
// TaintToleratedByTolerations checks if taint is tolerated by any of the tolerations. // TaintToleratedByTolerations checks if taint is tolerated by any of the tolerations.

View File

@ -51,19 +51,20 @@ func init() {
} }
var fileDescriptorGenerated = []byte{ var fileDescriptorGenerated = []byte{
// 222 bytes of a gzipped FileDescriptorProto // 236 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x32, 0xca, 0xb6, 0x28, 0xd6, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x6c, 0x8f, 0xa1, 0x4e, 0x03, 0x41,
0xcb, 0xcc, 0xd7, 0xcf, 0x2e, 0x4d, 0x4a, 0x2d, 0xca, 0x4b, 0x2d, 0x49, 0x2d, 0xd6, 0x2f, 0xc8, 0x10, 0x86, 0x67, 0x0d, 0x29, 0x27, 0x1b, 0x42, 0x48, 0xc5, 0x5e, 0x53, 0x45, 0x48, 0xd8, 0x09,
0x4e, 0xd7, 0x4f, 0x2c, 0xc8, 0xd4, 0x2f, 0x4a, 0x2d, 0xce, 0x2f, 0x2d, 0x4a, 0x4e, 0xd5, 0x4f, 0xa8, 0x06, 0xc9, 0x1b, 0x80, 0xc4, 0xdd, 0x95, 0x61, 0x99, 0x1c, 0xec, 0x6e, 0x76, 0x67, 0x05,
0x4f, 0xcd, 0x4b, 0x2d, 0x4a, 0x2c, 0x49, 0x4d, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x52, 0xae, 0x12, 0x59, 0x89, 0xec, 0xbd, 0x4d, 0x65, 0x25, 0x02, 0xc1, 0x1d, 0x2f, 0x42, 0x72, 0xa5,
0x82, 0xe8, 0xd1, 0x43, 0xe8, 0xd1, 0x03, 0xea, 0xd1, 0x03, 0xea, 0xd1, 0x83, 0xe9, 0x91, 0xd2, 0x21, 0x21, 0xb8, 0xf9, 0xc4, 0x37, 0xf9, 0xfe, 0xe2, 0xb2, 0x99, 0x27, 0xc3, 0x1e, 0x9b, 0x5c,
0x4d, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0x4f, 0xcf, 0xd7, 0x53, 0x74, 0x24, 0x94, 0x30, 0x34, 0x16, 0xab, 0xc0, 0x18, 0x29, 0xf9, 0x1c, 0x17, 0x84, 0x96,
0x07, 0x6b, 0x4d, 0x2a, 0x4d, 0x03, 0xf3, 0xc0, 0x1c, 0x30, 0x0b, 0x62, 0xa4, 0x94, 0x21, 0x76, 0x1c, 0xc5, 0x4a, 0xe8, 0xde, 0x84, 0xe8, 0xc5, 0x8f, 0x67, 0x3b, 0xc7, 0xfc, 0x3a, 0x26, 0x34,
0x67, 0x94, 0x96, 0x64, 0xe6, 0xe8, 0x67, 0xe6, 0x95, 0x14, 0x97, 0x14, 0xa1, 0xbb, 0x42, 0xc9, 0xd6, 0x54, 0x81, 0xcd, 0xde, 0x99, 0x9c, 0x5b, 0x96, 0xc7, 0x5c, 0x9b, 0x85, 0x7f, 0x46, 0xeb,
0x82, 0x8b, 0x23, 0xb0, 0x34, 0x31, 0xaf, 0x24, 0xb3, 0xa4, 0x52, 0x48, 0x8c, 0x8b, 0x0d, 0xa8, 0xad, 0xc7, 0x41, 0xad, 0xf3, 0xc3, 0x40, 0x03, 0x0c, 0xd7, 0xee, 0xe5, 0xe4, 0xe2, 0xff, 0x8c,
0x24, 0x33, 0x2f, 0x5d, 0x82, 0x51, 0x81, 0x51, 0x83, 0x33, 0x08, 0xca, 0xb3, 0x12, 0x99, 0xb1, 0x2c, 0xfc, 0x84, 0xec, 0x24, 0x49, 0xfc, 0x5b, 0x31, 0x9b, 0x17, 0xa3, 0x9b, 0x5c, 0x39, 0x61,
0x40, 0x9e, 0xa1, 0x63, 0xa1, 0x3c, 0xc3, 0x04, 0x20, 0x5e, 0x00, 0xc4, 0x0d, 0x77, 0x14, 0x18, 0x79, 0x19, 0x1f, 0x17, 0x07, 0x49, 0x22, 0x3b, 0x7b, 0xa2, 0xa6, 0xea, 0xf4, 0xf0, 0xf6, 0x87,
0x9c, 0xb4, 0x4e, 0x3c, 0x94, 0x63, 0xb8, 0x00, 0xc4, 0x37, 0x80, 0xb8, 0xe1, 0x91, 0x1c, 0xe3, 0xae, 0x8e, 0xde, 0xd6, 0x25, 0xbc, 0xb6, 0x25, 0xac, 0xda, 0x12, 0xd6, 0x6d, 0x09, 0xcb, 0x8f,
0x09, 0x20, 0xbe, 0x00, 0xc4, 0x0f, 0x80, 0x78, 0xc2, 0x63, 0x39, 0x86, 0x28, 0x0e, 0x98, 0x3f, 0x29, 0x5c, 0x9f, 0x6d, 0x3a, 0x0d, 0xdb, 0x4e, 0xc3, 0x7b, 0xa7, 0x61, 0xd9, 0x6b, 0xb5, 0xe9,
0x00, 0x01, 0x00, 0x00, 0xff, 0xff, 0x90, 0x1c, 0x7f, 0xff, 0x20, 0x01, 0x00, 0x00, 0xb5, 0xda, 0xf6, 0x5a, 0x7d, 0xf6, 0x5a, 0xad, 0xbe, 0x34, 0xdc, 0x8d, 0xf6, 0x3b, 0xbe, 0x03,
0x00, 0x00, 0xff, 0xff, 0x90, 0x1c, 0x7f, 0xff, 0x20, 0x01, 0x00, 0x00,
} }

View File

@ -21,7 +21,7 @@ syntax = 'proto2';
package k8s.io.kubernetes.pkg.api.resource; package k8s.io.kubernetes.pkg.api.resource;
import "k8s.io/client-go/pkg/util/intstr/generated.proto"; import "k8s.io/kubernetes/pkg/util/intstr/generated.proto";
// Package-wide variables from generator "generated". // Package-wide variables from generator "generated".
option go_package = "resource"; option go_package = "resource";

View File

@ -93,11 +93,11 @@ type TestGroup struct {
func init() { func init() {
if apiMediaType := os.Getenv("KUBE_TEST_API_TYPE"); len(apiMediaType) > 0 { if apiMediaType := os.Getenv("KUBE_TEST_API_TYPE"); len(apiMediaType) > 0 {
var ok bool var ok bool
mediaType, options, err := mime.ParseMediaType(apiMediaType) mediaType, _, err := mime.ParseMediaType(apiMediaType)
if err != nil { if err != nil {
panic(err) panic(err)
} }
serializer, ok = api.Codecs.SerializerForMediaType(mediaType, options) serializer, ok = runtime.SerializerInfoForMediaType(api.Codecs.SupportedMediaTypes(), mediaType)
if !ok { if !ok {
panic(fmt.Sprintf("no serializer for %s", apiMediaType)) panic(fmt.Sprintf("no serializer for %s", apiMediaType))
} }
@ -105,11 +105,11 @@ func init() {
if storageMediaType := StorageMediaType(); len(storageMediaType) > 0 { if storageMediaType := StorageMediaType(); len(storageMediaType) > 0 {
var ok bool var ok bool
mediaType, options, err := mime.ParseMediaType(storageMediaType) mediaType, _, err := mime.ParseMediaType(storageMediaType)
if err != nil { if err != nil {
panic(err) panic(err)
} }
storageSerializer, ok = api.Codecs.SerializerForMediaType(mediaType, options) storageSerializer, ok = runtime.SerializerInfoForMediaType(api.Codecs.SupportedMediaTypes(), mediaType)
if !ok { if !ok {
panic(fmt.Sprintf("no serializer for %s", storageMediaType)) panic(fmt.Sprintf("no serializer for %s", storageMediaType))
} }
@ -312,7 +312,7 @@ func (g TestGroup) Codec() runtime.Codec {
if serializer.Serializer == nil { if serializer.Serializer == nil {
return api.Codecs.LegacyCodec(g.externalGroupVersion) return api.Codecs.LegacyCodec(g.externalGroupVersion)
} }
return api.Codecs.CodecForVersions(serializer, api.Codecs.UniversalDeserializer(), unversioned.GroupVersions{g.externalGroupVersion}, nil) return api.Codecs.CodecForVersions(serializer.Serializer, api.Codecs.UniversalDeserializer(), unversioned.GroupVersions{g.externalGroupVersion}, nil)
} }
// NegotiatedSerializer returns the negotiated serializer for the server. // NegotiatedSerializer returns the negotiated serializer for the server.
@ -452,11 +452,11 @@ func GetCodecForObject(obj runtime.Object) (runtime.Codec, error) {
} }
// Codec used for unversioned types // Codec used for unversioned types
if api.Scheme.Recognizes(kind) { if api.Scheme.Recognizes(kind) {
serializer, ok := api.Codecs.SerializerForFileExtension("json") serializer, ok := runtime.SerializerInfoForMediaType(api.Codecs.SupportedMediaTypes(), runtime.ContentTypeJSON)
if !ok { if !ok {
return nil, fmt.Errorf("no serializer registered for json") return nil, fmt.Errorf("no serializer registered for json")
} }
return serializer, nil return serializer.Serializer, nil
} }
return nil, fmt.Errorf("unexpected kind: %v", kind) return nil, fmt.Errorf("unexpected kind: %v", kind)
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -16,5 +16,6 @@ limitations under the License.
// +k8s:deepcopy-gen=package // +k8s:deepcopy-gen=package
// +k8s:openapi-gen=true // +k8s:openapi-gen=true
// +k8s:defaulter-gen=TypeMeta
package unversioned package unversioned

View File

@ -4446,91 +4446,92 @@ var (
) )
var fileDescriptorGenerated = []byte{ var fileDescriptorGenerated = []byte{
// 1376 bytes of a gzipped FileDescriptorProto // 1390 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xcc, 0x57, 0xcd, 0x6f, 0x1b, 0x45, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xcc, 0x57, 0x4f, 0x6f, 0x1b, 0x45,
0x14, 0xf7, 0x47, 0xec, 0xae, 0x9f, 0x63, 0x92, 0x0e, 0xa9, 0x70, 0x2d, 0x11, 0x87, 0x45, 0xa0, 0x14, 0xf7, 0xda, 0xb1, 0xbb, 0x7e, 0x8e, 0x49, 0xba, 0xa4, 0x62, 0x1b, 0x09, 0xdb, 0x6c, 0x05,
0x54, 0x6a, 0x6d, 0x35, 0x02, 0x54, 0x15, 0xf1, 0x11, 0x27, 0x69, 0x15, 0x35, 0x49, 0xa3, 0x49, 0x4a, 0xa5, 0xd6, 0x56, 0x23, 0x40, 0x55, 0x11, 0x7f, 0xe2, 0x24, 0xad, 0xa2, 0x36, 0x6d, 0x34,
0x15, 0xa4, 0x16, 0x24, 0x36, 0xde, 0xb1, 0xb3, 0xb2, 0xbd, 0xbb, 0xec, 0xec, 0x56, 0x8d, 0x40, 0xa9, 0x8a, 0xd4, 0x16, 0x89, 0x8d, 0x77, 0xe2, 0xac, 0x6c, 0xef, 0x2e, 0x33, 0xb3, 0x51, 0x2d,
0xa2, 0x17, 0x24, 0x0e, 0x08, 0xe5, 0xc8, 0x05, 0xd4, 0x4a, 0xfc, 0x07, 0xfc, 0x13, 0x11, 0xa7, 0x90, 0xe8, 0xa5, 0x12, 0x07, 0x84, 0x7a, 0xe4, 0x02, 0x6a, 0xa5, 0x7e, 0x03, 0xbe, 0x44, 0xc5,
0x5e, 0x90, 0x38, 0xa0, 0x08, 0xca, 0x85, 0x2b, 0x57, 0x4e, 0xcc, 0xcc, 0xce, 0xec, 0x87, 0x53, 0xa9, 0x17, 0x24, 0x0e, 0xc8, 0xa2, 0xe1, 0xc2, 0x95, 0x6b, 0x4e, 0x68, 0x66, 0x67, 0xd6, 0xbb,
0x93, 0x0d, 0xf4, 0xc0, 0x61, 0x15, 0xcf, 0xfb, 0x9e, 0xf7, 0x7e, 0xf3, 0xde, 0x0b, 0xbc, 0x39, 0x6e, 0x4d, 0x36, 0xd0, 0x03, 0x27, 0xef, 0xfb, 0xff, 0xe6, 0xbd, 0xdf, 0xbc, 0x37, 0x86, 0xf7,
0xb8, 0x46, 0x5b, 0x96, 0xd3, 0x1e, 0x04, 0x7b, 0xc4, 0xb3, 0x89, 0x4f, 0x68, 0xdb, 0x1d, 0xf4, 0x7a, 0x17, 0x69, 0xd3, 0xf5, 0x5b, 0xbd, 0x70, 0x07, 0x13, 0x0f, 0x33, 0x4c, 0x5b, 0x41, 0xaf,
0xdb, 0x86, 0x6b, 0xb5, 0x03, 0xfb, 0x3e, 0xf1, 0xa8, 0xe5, 0xd8, 0xc4, 0x6c, 0xf7, 0x89, 0x4d, 0xdb, 0xb2, 0x03, 0xb7, 0x15, 0x7a, 0xfb, 0x98, 0x50, 0xd7, 0xf7, 0xb0, 0xd3, 0xea, 0x62, 0x0f,
0x3c, 0xc3, 0x27, 0x66, 0xcb, 0xf5, 0x1c, 0xdf, 0x41, 0xaf, 0x85, 0x6a, 0xad, 0x58, 0xad, 0xc5, 0x13, 0x9b, 0x61, 0xa7, 0x19, 0x10, 0x9f, 0xf9, 0xc6, 0xdb, 0x91, 0x59, 0x73, 0x6c, 0xd6, 0x0c,
0xd4, 0x5a, 0x4c, 0xad, 0x95, 0x50, 0x6b, 0x5c, 0xe9, 0x5b, 0xfe, 0x7e, 0xb0, 0xd7, 0xea, 0x3a, 0x7a, 0xdd, 0xa6, 0x1d, 0xb8, 0xcd, 0x84, 0xd9, 0xe2, 0xf9, 0xae, 0xcb, 0xf6, 0xc2, 0x9d, 0x66,
0xa3, 0x76, 0xdf, 0xe9, 0x3b, 0x6d, 0xa1, 0xbd, 0x17, 0xf4, 0xc4, 0x49, 0x1c, 0xc4, 0xaf, 0xd0, 0xc7, 0x1f, 0xb4, 0xba, 0x7e, 0xd7, 0x6f, 0x09, 0xeb, 0x9d, 0x70, 0x57, 0x50, 0x82, 0x10, 0x5f,
0x6a, 0xe3, 0xca, 0xb3, 0x83, 0xf1, 0x02, 0xdb, 0xb7, 0x46, 0x64, 0x3c, 0x88, 0xc6, 0xd5, 0x67, 0x91, 0xd7, 0xc5, 0xf3, 0x2f, 0x4f, 0x86, 0x84, 0x1e, 0x73, 0x07, 0x78, 0x32, 0x89, 0xc5, 0x0b,
0x8b, 0x07, 0xbe, 0x35, 0x6c, 0x5b, 0xb6, 0x4f, 0x7d, 0x6f, 0x5c, 0x45, 0xff, 0xb1, 0x08, 0xda, 0x2f, 0x57, 0x0f, 0x99, 0xdb, 0x6f, 0xb9, 0x1e, 0xa3, 0x8c, 0x4c, 0x9a, 0x58, 0x3f, 0x17, 0x40,
0xf2, 0xf6, 0xfa, 0x4d, 0xcf, 0x09, 0x5c, 0xb4, 0x00, 0x53, 0xb6, 0x31, 0x22, 0xf5, 0xfc, 0x42, 0x5f, 0xd9, 0xda, 0xb8, 0x42, 0xfc, 0x30, 0x30, 0x1a, 0x30, 0xe3, 0xd9, 0x03, 0x6c, 0x6a, 0x0d,
0x7e, 0xb1, 0xd2, 0x99, 0x3e, 0x3a, 0x6e, 0xe6, 0x9e, 0x1e, 0x37, 0xa7, 0xb6, 0x18, 0x0d, 0x0b, 0x6d, 0xa9, 0xdc, 0x9e, 0x7d, 0x3a, 0xaa, 0xe7, 0x0e, 0x46, 0xf5, 0x99, 0xeb, 0xf6, 0x00, 0x23,
0x0e, 0x1a, 0x81, 0x26, 0x2f, 0x43, 0xeb, 0x85, 0x85, 0xe2, 0x62, 0x75, 0xe9, 0xbd, 0x56, 0xa6, 0x21, 0x31, 0x06, 0xa0, 0xcb, 0xc3, 0x50, 0x33, 0xdf, 0x28, 0x2c, 0x55, 0x96, 0x3f, 0x6e, 0x66,
0x9b, 0xb7, 0x84, 0x87, 0xdd, 0xf0, 0x78, 0xc3, 0xf1, 0x56, 0x2d, 0xda, 0x75, 0x18, 0xf7, 0xa0, 0x3a, 0x79, 0x53, 0x44, 0xb8, 0x15, 0x91, 0x97, 0x7d, 0xb2, 0xe6, 0xd2, 0x8e, 0xbf, 0x8f, 0xc9,
0x33, 0x2b, 0xdd, 0x68, 0x92, 0x49, 0x71, 0xe4, 0x02, 0x7d, 0x91, 0x87, 0x59, 0xd7, 0x23, 0x3d, 0xb0, 0x3d, 0x2f, 0xc3, 0xe8, 0x52, 0x48, 0x51, 0x1c, 0xc2, 0x78, 0xa0, 0xc1, 0x7c, 0x40, 0xf0,
0xe2, 0x79, 0xc4, 0x94, 0xfc, 0x7a, 0x91, 0x45, 0xf7, 0x1c, 0xfc, 0xd6, 0xa5, 0xdf, 0xd9, 0xed, 0x2e, 0x26, 0x04, 0x3b, 0x52, 0x6e, 0x16, 0x1a, 0xda, 0xab, 0x88, 0x6b, 0xca, 0xb8, 0xf3, 0x5b,
0x31, 0x07, 0xf8, 0x84, 0x4b, 0xf4, 0x7d, 0x1e, 0x1a, 0x94, 0x78, 0x4c, 0x6f, 0xd9, 0x34, 0x3d, 0x13, 0x01, 0xd0, 0x0b, 0x21, 0x8d, 0x27, 0x1a, 0x2c, 0x52, 0x4c, 0xf6, 0x31, 0x59, 0x71, 0x1c,
0x42, 0x69, 0xe7, 0x60, 0x65, 0x68, 0x11, 0xdb, 0x5f, 0x59, 0x5f, 0xc5, 0xb4, 0x3e, 0x25, 0x32, 0x82, 0x29, 0x6d, 0x0f, 0x57, 0xfb, 0x2e, 0xf6, 0xd8, 0xea, 0xc6, 0x1a, 0xa2, 0xe6, 0x8c, 0xa8,
0xf1, 0x7e, 0xc6, 0x88, 0x76, 0x26, 0x19, 0xea, 0xe8, 0x32, 0xa4, 0xc6, 0x44, 0x11, 0x8a, 0xff, 0xc4, 0x27, 0x19, 0x33, 0xda, 0x9e, 0xe6, 0xa8, 0x6d, 0xc9, 0x94, 0x16, 0xa7, 0xaa, 0x50, 0xf4,
0x21, 0x0e, 0xbd, 0x0f, 0xd3, 0xaa, 0x96, 0x1b, 0x16, 0xf5, 0xd1, 0x07, 0x50, 0xee, 0xf3, 0x03, 0x0f, 0x79, 0x58, 0x5d, 0x98, 0x55, 0xbd, 0xbc, 0xe6, 0x52, 0x66, 0x7c, 0x0a, 0xa5, 0x2e, 0x27,
0x65, 0x15, 0xe5, 0x11, 0xb6, 0x33, 0x46, 0xa8, 0x8c, 0x74, 0x5e, 0x90, 0x01, 0x95, 0xc5, 0x91, 0xa8, 0xa9, 0x89, 0x0c, 0x5b, 0x19, 0x33, 0x54, 0x4e, 0xda, 0xaf, 0xc9, 0x84, 0x4a, 0x82, 0xa4,
0x62, 0x69, 0x4e, 0x67, 0x75, 0xa9, 0x32, 0x21, 0x4c, 0xa8, 0x13, 0x78, 0x5d, 0x92, 0x01, 0x38, 0x48, 0xba, 0xb3, 0x1e, 0x68, 0x50, 0x59, 0xd9, 0xda, 0x40, 0x98, 0xfa, 0x21, 0xe9, 0xe0, 0x0c,
0x4b, 0x00, 0xfc, 0x2f, 0x75, 0x8d, 0x2e, 0x31, 0x19, 0x74, 0xf2, 0x8b, 0x5a, 0x07, 0x49, 0x39, 0xc0, 0x59, 0x06, 0xe0, 0xbf, 0x34, 0xb0, 0x3b, 0xd8, 0x31, 0xf3, 0x0d, 0x6d, 0x49, 0x6f, 0x1b,
0xd8, 0x8a, 0x38, 0x38, 0x21, 0xc5, 0xad, 0x0e, 0x2c, 0xdb, 0x14, 0x05, 0x4f, 0x58, 0xbd, 0xc5, 0x52, 0x0f, 0xae, 0xc7, 0x12, 0x94, 0xd0, 0xe2, 0x5e, 0x7b, 0xae, 0xe7, 0x88, 0x86, 0x27, 0xbc,
0x68, 0x58, 0x70, 0xf4, 0x1f, 0xf2, 0x30, 0x93, 0x88, 0x43, 0x5c, 0xfa, 0x1a, 0x4c, 0xf7, 0x13, 0x5e, 0x75, 0x3d, 0x07, 0x09, 0x89, 0xf5, 0x93, 0x06, 0x73, 0x89, 0x3c, 0xc4, 0xa1, 0x2f, 0xc2,
0x35, 0x97, 0x31, 0xcd, 0x49, 0xed, 0xe9, 0x24, 0x1e, 0x70, 0x4a, 0x12, 0xf5, 0xa0, 0xe2, 0x49, 0x6c, 0x37, 0xd1, 0x73, 0x99, 0xd3, 0x82, 0xb4, 0x9e, 0x4d, 0xe2, 0x01, 0xa5, 0x34, 0x8d, 0x5d,
0x4b, 0x0a, 0xdd, 0x4b, 0xd9, 0x33, 0xa6, 0x82, 0x88, 0x5d, 0x25, 0x88, 0x14, 0xc7, 0xa6, 0xf5, 0x28, 0x13, 0xe9, 0x49, 0xa1, 0x7b, 0x39, 0x7b, 0xc5, 0x54, 0x12, 0xe3, 0x50, 0x09, 0x26, 0x45,
0x3f, 0xc2, 0xec, 0x29, 0xbc, 0xa3, 0xc5, 0xc4, 0xa3, 0xe2, 0x85, 0x62, 0x77, 0x9d, 0xf0, 0x1e, 0x63, 0xd7, 0xd6, 0x9f, 0x51, 0xf5, 0x14, 0xde, 0x8d, 0xa5, 0xc4, 0xa5, 0xe2, 0x8d, 0x2a, 0xb7,
0x4e, 0xc1, 0x61, 0xe1, 0xff, 0x81, 0xc3, 0xeb, 0xda, 0x37, 0x8f, 0x9a, 0xb9, 0x87, 0xbf, 0x2c, 0x67, 0xa7, 0xdc, 0x87, 0x23, 0x70, 0x98, 0xff, 0x7f, 0xe0, 0xf0, 0x92, 0xfe, 0xfd, 0xa3, 0x7a,
0xe4, 0xf4, 0x75, 0xd0, 0x56, 0x03, 0xd6, 0x6f, 0x78, 0x7a, 0xdf, 0x01, 0xcd, 0x94, 0xbf, 0x45, 0xee, 0xfe, 0x6f, 0x8d, 0x9c, 0xb5, 0x01, 0xfa, 0x5a, 0x48, 0x6c, 0xc6, 0xcb, 0xfb, 0x21, 0xe8,
0x51, 0x8a, 0x9d, 0x57, 0xd4, 0xd3, 0x57, 0x32, 0x7f, 0x1d, 0x37, 0x6b, 0xbc, 0xb3, 0xb5, 0x14, 0x8e, 0xfc, 0x16, 0x4d, 0x29, 0xb4, 0xdf, 0x52, 0x57, 0x5f, 0xe9, 0x1c, 0x8e, 0xea, 0x55, 0x3e,
0x01, 0x47, 0x2a, 0xfa, 0x87, 0x50, 0x5b, 0x7b, 0xe0, 0x3a, 0x9e, 0x7f, 0xdb, 0xf5, 0x45, 0x32, 0xd9, 0x9a, 0x8a, 0x81, 0x62, 0x13, 0xeb, 0x2e, 0x54, 0xd7, 0xef, 0x05, 0x3e, 0x61, 0x37, 0x02,
0x5e, 0x87, 0x32, 0x11, 0x04, 0x61, 0x4d, 0x8b, 0xc1, 0x1a, 0x8a, 0x61, 0xc9, 0x45, 0xaf, 0x42, 0x26, 0x8a, 0xf1, 0x0e, 0x94, 0xb0, 0x60, 0x08, 0x6f, 0xfa, 0x18, 0xac, 0x91, 0x1a, 0x92, 0x52,
0x89, 0x3c, 0x30, 0xba, 0xbe, 0x44, 0x5d, 0x4d, 0x8a, 0x95, 0xd6, 0x38, 0x11, 0x87, 0x3c, 0x66, 0xe3, 0x0c, 0x14, 0xf1, 0x3d, 0xbb, 0xc3, 0x24, 0xea, 0xaa, 0x52, 0xad, 0xb8, 0xce, 0x99, 0x28,
0xbd, 0x22, 0x90, 0xc1, 0xc1, 0xc5, 0x35, 0x04, 0x30, 0x24, 0x76, 0x22, 0x0d, 0x21, 0x81, 0x43, 0x92, 0x59, 0x77, 0xa1, 0x2c, 0x90, 0xc1, 0xc1, 0xc5, 0x2d, 0x04, 0x30, 0x24, 0x76, 0x62, 0x0b,
0x5e, 0x84, 0xce, 0xc2, 0x24, 0x74, 0x26, 0xd2, 0x30, 0x84, 0x5a, 0xa8, 0xab, 0x1e, 0x4c, 0x26, 0xa1, 0x81, 0x22, 0x59, 0x8c, 0xce, 0xfc, 0x34, 0x74, 0x26, 0xca, 0xd0, 0x87, 0x6a, 0x64, 0xab,
0x0f, 0x97, 0x41, 0x53, 0xa0, 0x91, 0x5e, 0xa2, 0x5e, 0xa9, 0x0c, 0xe1, 0x48, 0x22, 0xe1, 0x6d, 0x2e, 0x4c, 0xa6, 0x08, 0xe7, 0x40, 0x57, 0xa0, 0x91, 0x51, 0xe2, 0x59, 0xa9, 0x1c, 0xa1, 0x58,
0x1f, 0x52, 0x28, 0xcf, 0xe6, 0xec, 0x12, 0x9c, 0x93, 0xd0, 0x90, 0xbe, 0x66, 0xa4, 0xd8, 0x39, 0x23, 0x11, 0x6d, 0x0f, 0x52, 0x28, 0xcf, 0x16, 0xec, 0x2c, 0x9c, 0x90, 0xd0, 0x90, 0xb1, 0xe6,
0xf5, 0x58, 0x14, 0x3f, 0xe1, 0xe9, 0x73, 0xa8, 0x4f, 0xea, 0xaf, 0xff, 0xe1, 0x1d, 0x66, 0x0f, 0xa4, 0xda, 0x09, 0x75, 0x59, 0x94, 0x3c, 0x11, 0xe9, 0x6b, 0x30, 0xa7, 0xcd, 0xd7, 0xff, 0x70,
0x45, 0xff, 0x9a, 0x0d, 0x88, 0xa4, 0xa5, 0xec, 0xe5, 0xcb, 0xee, 0xe4, 0xf4, 0x3e, 0x94, 0xc8, 0x0f, 0xb3, 0xa7, 0x62, 0x7d, 0xa7, 0xc1, 0x7c, 0xd2, 0x53, 0xf6, 0xf6, 0x65, 0x0f, 0x72, 0xf4,
0xc8, 0x77, 0x79, 0x98, 0x4b, 0x5d, 0xed, 0x4c, 0x15, 0x3f, 0x43, 0x50, 0x49, 0x70, 0x14, 0xcf, 0x1c, 0x4a, 0x54, 0xe4, 0x47, 0x0d, 0x16, 0x52, 0x47, 0x3b, 0x56, 0xc7, 0x8f, 0x91, 0x54, 0x12,
0x00, 0x8e, 0x9f, 0x0a, 0x50, 0xdb, 0x30, 0xf6, 0xc8, 0x70, 0x87, 0x0c, 0x49, 0xd7, 0x77, 0x3c, 0x1c, 0x85, 0x63, 0x80, 0xe3, 0x97, 0x3c, 0x54, 0xaf, 0xd9, 0x3b, 0xb8, 0xbf, 0x8d, 0xfb, 0xb8,
0xf4, 0x19, 0x54, 0x47, 0x86, 0xdf, 0xdd, 0x17, 0x54, 0x35, 0x2a, 0xd6, 0x32, 0x36, 0x91, 0x94, 0xc3, 0x7c, 0x62, 0x7c, 0x05, 0x95, 0x81, 0xcd, 0x3a, 0x7b, 0x82, 0xab, 0x56, 0xc5, 0x7a, 0xc6,
0xa9, 0xd6, 0x66, 0x6c, 0x67, 0xcd, 0xf6, 0xd9, 0x90, 0x7d, 0x51, 0xc6, 0x54, 0x4d, 0x70, 0x70, 0x21, 0x92, 0x72, 0xd5, 0xdc, 0x1c, 0xfb, 0x59, 0xf7, 0x18, 0x19, 0xb6, 0x5f, 0x97, 0x39, 0x55,
0xd2, 0x9d, 0x18, 0xf1, 0xe2, 0xcc, 0x5e, 0x2d, 0xef, 0x24, 0xff, 0x62, 0xb5, 0x48, 0xc5, 0x80, 0x12, 0x12, 0x94, 0x0c, 0x27, 0x56, 0xbc, 0xa0, 0xd7, 0xef, 0x05, 0x7c, 0x92, 0xfc, 0x8b, 0xa7,
0xc9, 0x27, 0x81, 0xe5, 0x91, 0x11, 0x6b, 0x46, 0xf1, 0x88, 0xdf, 0x1c, 0x73, 0x80, 0x4f, 0xb8, 0x45, 0x2a, 0x07, 0x84, 0xbf, 0x08, 0x5d, 0x82, 0x07, 0xd8, 0x63, 0xe3, 0x15, 0xbf, 0x39, 0x11,
0x6c, 0xbc, 0x0b, 0xb3, 0xe3, 0xd1, 0xa3, 0x59, 0x28, 0x0e, 0xc8, 0x41, 0x58, 0x31, 0xcc, 0x7f, 0x00, 0xbd, 0x10, 0x72, 0xf1, 0x23, 0x98, 0x9f, 0xcc, 0xde, 0x98, 0x87, 0x42, 0x0f, 0x0f, 0xa3,
0xa2, 0x39, 0x28, 0xdd, 0x37, 0x86, 0x81, 0x7c, 0x8f, 0x38, 0x3c, 0x5c, 0x2f, 0x5c, 0xcb, 0xeb, 0x8e, 0x21, 0xfe, 0x69, 0x2c, 0x40, 0x71, 0xdf, 0xee, 0x87, 0xf2, 0x3e, 0xa2, 0x88, 0xb8, 0x94,
0xac, 0x35, 0xd7, 0x27, 0x05, 0x82, 0x5e, 0x4e, 0x18, 0xea, 0x54, 0x65, 0x54, 0xc5, 0x5b, 0xe4, 0xbf, 0xa8, 0x59, 0x4f, 0x34, 0x30, 0xa7, 0x25, 0x62, 0xbc, 0x99, 0x70, 0xd4, 0xae, 0xc8, 0xac,
0x20, 0xb4, 0xba, 0x06, 0x9a, 0xe3, 0xf2, 0xb5, 0xcc, 0xf1, 0x64, 0xdd, 0x2f, 0xa9, 0x5a, 0xde, 0x0a, 0x57, 0xf1, 0x30, 0xf2, 0xba, 0x0e, 0xba, 0x1f, 0xf0, 0x67, 0x99, 0x4f, 0x64, 0xdf, 0xcf,
0x96, 0x74, 0xd6, 0x19, 0x2f, 0xa4, 0xcc, 0x2b, 0x06, 0x8e, 0x54, 0x91, 0x0e, 0x65, 0x11, 0x0f, 0xaa, 0x5e, 0xde, 0x90, 0xfc, 0xc3, 0x51, 0xfd, 0x54, 0xca, 0xbd, 0x12, 0xa0, 0xd8, 0xd4, 0xb0,
0x65, 0x80, 0xe0, 0x53, 0x04, 0x78, 0x33, 0xdc, 0x15, 0x14, 0x2c, 0x39, 0xfa, 0xa7, 0xa0, 0xf1, 0xa0, 0x24, 0xf2, 0xa1, 0x66, 0x41, 0x6c, 0x11, 0xe0, 0xc3, 0xf0, 0x96, 0xe0, 0x20, 0x29, 0xb1,
0x29, 0xb9, 0x49, 0x7c, 0x83, 0x43, 0x88, 0x92, 0x61, 0x6f, 0xc3, 0xb2, 0x07, 0x32, 0xb4, 0x08, 0xbe, 0x04, 0x9d, 0x6f, 0xc9, 0x4d, 0xcc, 0x6c, 0x0e, 0x21, 0x8a, 0xfb, 0xbb, 0xd7, 0x5c, 0xaf,
0x42, 0x3b, 0x92, 0x8e, 0x23, 0x09, 0xb4, 0x0c, 0x33, 0x0a, 0x4e, 0xbb, 0x29, 0x8c, 0xbe, 0x24, 0x27, 0x53, 0x8b, 0x21, 0xb4, 0x2d, 0xf9, 0x28, 0xd6, 0x30, 0x56, 0x60, 0x4e, 0xc1, 0xe9, 0x56,
0x95, 0x66, 0x70, 0x9a, 0x8d, 0xc7, 0xe5, 0xf5, 0xcb, 0x50, 0xc1, 0x8e, 0xe3, 0x6f, 0x1b, 0xfe, 0x0a, 0xa3, 0x6f, 0x48, 0xa3, 0x39, 0x94, 0x16, 0xa3, 0x49, 0x7d, 0xeb, 0x1c, 0x94, 0x91, 0xef,
0x3e, 0x45, 0x4d, 0x28, 0xb9, 0xfc, 0x87, 0x1c, 0x79, 0x15, 0xfe, 0x18, 0x04, 0x07, 0x87, 0x74, 0xb3, 0x2d, 0x9b, 0xed, 0x51, 0xa3, 0x0e, 0xc5, 0x80, 0x7f, 0xc8, 0x95, 0x57, 0xe6, 0x97, 0x41,
0xfd, 0xab, 0x3c, 0x5c, 0x9c, 0x38, 0x80, 0xf8, 0x42, 0xd1, 0x8d, 0x4e, 0x32, 0xfc, 0x68, 0xa1, 0x48, 0x50, 0xc4, 0xb7, 0xbe, 0xd5, 0xe0, 0xf4, 0xd4, 0x05, 0xc4, 0x1f, 0x14, 0x9d, 0x98, 0x92,
0x88, 0xe5, 0x70, 0x42, 0x0a, 0xbd, 0x0d, 0xb5, 0xd4, 0xd4, 0x92, 0x17, 0xb8, 0x20, 0xd5, 0x6a, 0xe9, 0xc7, 0x0f, 0x8a, 0xb1, 0x1e, 0x4a, 0x68, 0x19, 0x1f, 0x40, 0x35, 0xb5, 0xb5, 0xe4, 0x01,
0x29, 0x6f, 0x38, 0x2d, 0xab, 0xff, 0x59, 0x80, 0xf2, 0x8e, 0x6f, 0xf8, 0x01, 0x45, 0x1f, 0x81, 0x4e, 0x49, 0xb3, 0x6a, 0x2a, 0x1a, 0x4a, 0xeb, 0x5a, 0x7f, 0xe5, 0xa1, 0xb4, 0xcd, 0x6c, 0x16,
0x36, 0x62, 0x09, 0x34, 0x0d, 0xdf, 0x10, 0x9e, 0xb3, 0x6f, 0x56, 0x2a, 0xf7, 0x71, 0xa6, 0x15, 0x52, 0xe3, 0x33, 0xd0, 0x07, 0x98, 0xd9, 0x8e, 0xcd, 0x6c, 0x11, 0x39, 0xfb, 0xcb, 0x4a, 0xd5,
0x05, 0x47, 0x26, 0xf9, 0x60, 0xa3, 0xc2, 0x91, 0x8c, 0x2f, 0x1a, 0x6c, 0xa1, 0x7b, 0x2c, 0xb9, 0x7e, 0x5c, 0x69, 0xc5, 0x41, 0xb1, 0x4b, 0xbe, 0xd8, 0xa8, 0x08, 0x24, 0xf3, 0x8b, 0x17, 0x5b,
0xbc, 0x5b, 0xb0, 0x5d, 0x89, 0x1a, 0x7d, 0xd5, 0x01, 0xa2, 0x6e, 0xb1, 0x19, 0x92, 0xb1, 0xe2, 0x14, 0x1e, 0x49, 0x29, 0x9f, 0x16, 0x03, 0x4c, 0xa9, 0xdd, 0x55, 0x13, 0x20, 0x9e, 0x16, 0x9b,
0xa3, 0xb7, 0xa0, 0xec, 0x11, 0x83, 0xb2, 0x9a, 0x4d, 0x09, 0xc9, 0x79, 0x65, 0x12, 0x0b, 0x2a, 0x11, 0x1b, 0x29, 0xb9, 0xf1, 0x3e, 0x94, 0x08, 0xb6, 0xa9, 0xef, 0x99, 0x33, 0x42, 0xb3, 0xa6,
0x43, 0xd7, 0xb4, 0x34, 0x2e, 0xce, 0x58, 0x4a, 0xa3, 0x7b, 0x70, 0xce, 0x64, 0x61, 0x59, 0xac, 0x5c, 0x22, 0xc1, 0x3d, 0x1c, 0xd5, 0x67, 0xa5, 0x73, 0x41, 0x23, 0xa9, 0x6d, 0xdc, 0x81, 0x13,
0x2f, 0x94, 0xc4, 0x45, 0xdf, 0xc8, 0xba, 0x5c, 0x08, 0x6b, 0xab, 0xa1, 0x6e, 0xa7, 0xca, 0x83, 0x0e, 0x66, 0xb6, 0xdb, 0xa7, 0x66, 0x51, 0x1c, 0xf4, 0xdd, 0xac, 0x8f, 0x0b, 0xe1, 0x6d, 0x2d,
0x92, 0x07, 0xac, 0x2c, 0xf2, 0xbe, 0xda, 0x75, 0x4c, 0x52, 0x2f, 0x33, 0xcb, 0xa5, 0xb8, 0xaf, 0xb2, 0x6d, 0x57, 0x78, 0x52, 0x92, 0x40, 0xca, 0x23, 0x9f, 0xab, 0x1d, 0xdf, 0xc1, 0x66, 0xa9,
0xae, 0x30, 0x1a, 0x16, 0x1c, 0xfd, 0x90, 0x6d, 0x4a, 0xa1, 0xa5, 0x15, 0x23, 0xa0, 0x04, 0x5d, 0xa1, 0x2d, 0x15, 0xc7, 0x73, 0x75, 0xd5, 0x77, 0x30, 0x12, 0x12, 0xeb, 0xa1, 0x06, 0x95, 0xc8,
0x8d, 0xae, 0x11, 0x16, 0xfc, 0xa2, 0xd2, 0xb9, 0x73, 0xe0, 0x12, 0x76, 0x89, 0x8a, 0x10, 0xe3, 0xd3, 0xaa, 0x1d, 0x52, 0x6c, 0x5c, 0x88, 0x8f, 0x11, 0x35, 0xfc, 0xb4, 0xb2, 0xb9, 0x39, 0x0c,
0x87, 0xe8, 0x06, 0x89, 0x24, 0x15, 0x4e, 0x49, 0x12, 0x6b, 0xd1, 0x3d, 0x8b, 0x0c, 0x55, 0xa3, 0xf0, 0xe1, 0xa8, 0x5e, 0x16, 0x6a, 0x9c, 0x88, 0x4f, 0x90, 0x28, 0x52, 0xfe, 0x88, 0x22, 0x9d,
0x8f, 0x5a, 0xf4, 0x0d, 0x4e, 0xc4, 0x21, 0x4f, 0xff, 0x96, 0xf5, 0xcf, 0xd4, 0xe5, 0x32, 0x2c, 0x81, 0xe2, 0xae, 0x8b, 0xfb, 0x6a, 0xd0, 0xc7, 0x23, 0xfa, 0x32, 0x67, 0xa2, 0x48, 0x66, 0xfd,
0xbf, 0x51, 0xef, 0x2f, 0x64, 0xd8, 0x27, 0x26, 0x4e, 0x19, 0x74, 0x17, 0xca, 0x5d, 0x7e, 0x3f, 0x90, 0x87, 0x6a, 0xea, 0x70, 0x19, 0x1e, 0xbf, 0xf1, 0xec, 0xcf, 0x67, 0x78, 0x4f, 0x4c, 0xdd,
0xf5, 0x0f, 0xc7, 0xd2, 0x99, 0x6a, 0x21, 0x52, 0x13, 0x63, 0x49, 0x1c, 0x19, 0x96, 0x42, 0x8b, 0x32, 0xc6, 0x6d, 0x28, 0x75, 0xf8, 0xf9, 0xd4, 0x1f, 0x8e, 0xe5, 0x63, 0xf5, 0x42, 0x94, 0x66,
0xe8, 0x26, 0x9c, 0xf7, 0x08, 0xeb, 0x79, 0xcb, 0x3d, 0x9f, 0x78, 0x3b, 0xa4, 0xeb, 0xd8, 0x66, 0x8c, 0x25, 0x41, 0x52, 0x24, 0x3d, 0x1a, 0x57, 0xe0, 0x24, 0xc1, 0x8c, 0x0c, 0x57, 0x76, 0x19,
0x58, 0xf2, 0x52, 0x94, 0xe4, 0xf3, 0x78, 0x5c, 0x00, 0x9f, 0xd4, 0x61, 0xab, 0xce, 0xd4, 0x1d, 0x26, 0xdb, 0xb8, 0xe3, 0x7b, 0x4e, 0xd4, 0xf2, 0x62, 0x5c, 0xe4, 0x93, 0x68, 0x52, 0x01, 0xbd,
0xb6, 0xc1, 0xf1, 0xbc, 0x53, 0x69, 0x26, 0x5c, 0xf6, 0xa2, 0xbc, 0x2b, 0x65, 0xc5, 0xe7, 0xe9, 0x68, 0x63, 0xf5, 0x61, 0xe6, 0xa6, 0x3b, 0xc0, 0xbc, 0xee, 0x54, 0xba, 0x89, 0x1e, 0x7b, 0x71,
0xb1, 0x0d, 0xdb, 0x09, 0xe1, 0x5e, 0x8a, 0xd3, 0xb3, 0xc5, 0x89, 0x38, 0xe4, 0x5d, 0x9f, 0xe3, 0xdd, 0x95, 0xb1, 0x92, 0xf3, 0xf2, 0x78, 0xb6, 0xe7, 0x47, 0x70, 0x2f, 0x8e, 0xcb, 0x73, 0x9d,
0x13, 0xec, 0xcb, 0xc7, 0xcd, 0xdc, 0x21, 0xfb, 0x1e, 0x3d, 0x96, 0xd3, 0xec, 0x1e, 0x54, 0xb8, 0x33, 0x51, 0x24, 0xbb, 0xb4, 0xc0, 0x37, 0xd8, 0x37, 0x8f, 0xeb, 0xb9, 0x87, 0x8f, 0xeb, 0xb9,
0x37, 0xf6, 0x20, 0x46, 0xee, 0xf3, 0x76, 0xa9, 0x7f, 0x0c, 0x1a, 0x87, 0x92, 0xe8, 0x95, 0xaa, 0x47, 0x8f, 0xe5, 0x36, 0xbb, 0x03, 0x65, 0x1e, 0x8d, 0x32, 0x7b, 0x10, 0xbc, 0xea, 0x90, 0xd6,
0x3a, 0xf9, 0x89, 0xd5, 0x61, 0x0d, 0x89, 0x25, 0x3e, 0xdd, 0x1a, 0xa3, 0x86, 0x14, 0xaf, 0xfb, 0xe7, 0xa0, 0x73, 0x28, 0x89, 0x59, 0xa9, 0xba, 0xa3, 0x4d, 0xed, 0xce, 0x32, 0x80, 0x1d, 0xb8,
0x38, 0x21, 0xd5, 0xb9, 0x72, 0xf4, 0xdb, 0x7c, 0xee, 0x09, 0xfb, 0x7e, 0x66, 0xdf, 0xc3, 0xa7, 0xe9, 0xd1, 0x18, 0x0f, 0xa4, 0xf1, 0x73, 0x1f, 0x25, 0xb4, 0xda, 0xe7, 0x9f, 0x3e, 0xaf, 0xe5,
0xf3, 0xf9, 0x23, 0xf6, 0x3d, 0x61, 0xdf, 0xaf, 0xec, 0x3b, 0xfc, 0x7d, 0x3e, 0x77, 0xb7, 0x9a, 0x9e, 0x3d, 0xaf, 0xe5, 0x7e, 0x7d, 0x5e, 0xcb, 0xdd, 0x3f, 0xa8, 0x69, 0x4f, 0x0f, 0x6a, 0xda,
0x28, 0xe4, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x0a, 0x22, 0x00, 0xde, 0x9c, 0x10, 0x00, 0x00, 0xb3, 0x83, 0x9a, 0xf6, 0xfb, 0x41, 0x4d, 0x7b, 0xf8, 0x47, 0x2d, 0x77, 0xbb, 0x92, 0x68, 0xe4,
0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x0a, 0x22, 0x00, 0xde, 0x9c, 0x10, 0x00, 0x00,
} }

View File

@ -21,8 +21,8 @@ syntax = 'proto2';
package k8s.io.kubernetes.pkg.api.unversioned; package k8s.io.kubernetes.pkg.api.unversioned;
import "k8s.io/client-go/pkg/runtime/generated.proto"; import "k8s.io/kubernetes/pkg/runtime/generated.proto";
import "k8s.io/client-go/pkg/util/intstr/generated.proto"; import "k8s.io/kubernetes/pkg/util/intstr/generated.proto";
// Package-wide variables from generator "generated". // Package-wide variables from generator "generated".
option go_package = "unversioned"; option go_package = "unversioned";
@ -38,6 +38,7 @@ message APIGroup {
// preferredVersion is the version preferred by the API server, which // preferredVersion is the version preferred by the API server, which
// probably is the storage version. // probably is the storage version.
// +optional
optional GroupVersionForDiscovery preferredVersion = 3; optional GroupVersionForDiscovery preferredVersion = 3;
// a map of client CIDR to server address that is serving this group. // a map of client CIDR to server address that is serving this group.
@ -185,9 +186,11 @@ message LabelSelector {
// matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels // matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
// map is equivalent to an element of matchExpressions, whose key field is "key", the // map is equivalent to an element of matchExpressions, whose key field is "key", the
// operator is "In", and the values array contains only "value". The requirements are ANDed. // operator is "In", and the values array contains only "value". The requirements are ANDed.
// +optional
map<string, string> matchLabels = 1; map<string, string> matchLabels = 1;
// matchExpressions is a list of label selector requirements. The requirements are ANDed. // matchExpressions is a list of label selector requirements. The requirements are ANDed.
// +optional
repeated LabelSelectorRequirement matchExpressions = 2; repeated LabelSelectorRequirement matchExpressions = 2;
} }
@ -205,6 +208,7 @@ message LabelSelectorRequirement {
// the values array must be non-empty. If the operator is Exists or DoesNotExist, // the values array must be non-empty. If the operator is Exists or DoesNotExist,
// the values array must be empty. This array is replaced during a strategic // the values array must be empty. This array is replaced during a strategic
// merge patch. // merge patch.
// +optional
repeated string values = 3; repeated string values = 3;
} }
@ -214,6 +218,7 @@ message ListMeta {
// SelfLink is a URL representing this object. // SelfLink is a URL representing this object.
// Populated by the system. // Populated by the system.
// Read-only. // Read-only.
// +optional
optional string selfLink = 1; optional string selfLink = 1;
// String that identifies the server's internal version of this object that // String that identifies the server's internal version of this object that
@ -222,6 +227,7 @@ message ListMeta {
// Populated by the system. // Populated by the system.
// Read-only. // Read-only.
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#concurrency-control-and-consistency // More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#concurrency-control-and-consistency
// +optional
optional string resourceVersion = 2; optional string resourceVersion = 2;
} }
@ -246,29 +252,35 @@ message ServerAddressByClientCIDR {
message Status { message Status {
// Standard list metadata. // Standard list metadata.
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds // More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds
// +optional
optional ListMeta metadata = 1; optional ListMeta metadata = 1;
// Status of the operation. // Status of the operation.
// One of: "Success" or "Failure". // One of: "Success" or "Failure".
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#spec-and-status // More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#spec-and-status
// +optional
optional string status = 2; optional string status = 2;
// A human-readable description of the status of this operation. // A human-readable description of the status of this operation.
// +optional
optional string message = 3; optional string message = 3;
// A machine-readable description of why this operation is in the // A machine-readable description of why this operation is in the
// "Failure" status. If this value is empty there // "Failure" status. If this value is empty there
// is no information available. A Reason clarifies an HTTP status // is no information available. A Reason clarifies an HTTP status
// code but does not override it. // code but does not override it.
// +optional
optional string reason = 4; optional string reason = 4;
// Extended data associated with the reason. Each reason may define its // Extended data associated with the reason. Each reason may define its
// own extended details. This field is optional and the data returned // own extended details. This field is optional and the data returned
// is not guaranteed to conform to any schema except that defined by // is not guaranteed to conform to any schema except that defined by
// the reason type. // the reason type.
// +optional
optional StatusDetails details = 5; optional StatusDetails details = 5;
// Suggested HTTP return code for this status, 0 if not set. // Suggested HTTP return code for this status, 0 if not set.
// +optional
optional int32 code = 6; optional int32 code = 6;
} }
@ -277,10 +289,12 @@ message Status {
message StatusCause { message StatusCause {
// A machine-readable description of the cause of the error. If this value is // A machine-readable description of the cause of the error. If this value is
// empty there is no information available. // empty there is no information available.
// +optional
optional string reason = 1; optional string reason = 1;
// A human-readable description of the cause of the error. This field may be // A human-readable description of the cause of the error. This field may be
// presented as-is to a reader. // presented as-is to a reader.
// +optional
optional string message = 2; optional string message = 2;
// The field of the resource that has caused this error, as named by its JSON // The field of the resource that has caused this error, as named by its JSON
@ -292,6 +306,7 @@ message StatusCause {
// Examples: // Examples:
// "name" - the field "name" on the current resource // "name" - the field "name" on the current resource
// "items[0].name" - the field "name" on the first array entry in "items" // "items[0].name" - the field "name" on the first array entry in "items"
// +optional
optional string field = 3; optional string field = 3;
} }
@ -304,21 +319,26 @@ message StatusCause {
message StatusDetails { message StatusDetails {
// The name attribute of the resource associated with the status StatusReason // The name attribute of the resource associated with the status StatusReason
// (when there is a single name which can be described). // (when there is a single name which can be described).
// +optional
optional string name = 1; optional string name = 1;
// The group attribute of the resource associated with the status StatusReason. // The group attribute of the resource associated with the status StatusReason.
// +optional
optional string group = 2; optional string group = 2;
// The kind attribute of the resource associated with the status StatusReason. // The kind attribute of the resource associated with the status StatusReason.
// On some operations may differ from the requested resource Kind. // On some operations may differ from the requested resource Kind.
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds // More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds
// +optional
optional string kind = 3; optional string kind = 3;
// The Causes array includes more details associated with the StatusReason // The Causes array includes more details associated with the StatusReason
// failure. Not all StatusReasons may provide detailed causes. // failure. Not all StatusReasons may provide detailed causes.
// +optional
repeated StatusCause causes = 4; repeated StatusCause causes = 4;
// If specified, the time in seconds before the operation should be retried. // If specified, the time in seconds before the operation should be retried.
// +optional
optional int32 retryAfterSeconds = 5; optional int32 retryAfterSeconds = 5;
} }
@ -367,12 +387,14 @@ message TypeMeta {
// Cannot be updated. // Cannot be updated.
// In CamelCase. // In CamelCase.
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds // More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds
// +optional
optional string kind = 1; optional string kind = 1;
// APIVersion defines the versioned schema of this representation of an object. // APIVersion defines the versioned schema of this representation of an object.
// Servers should convert recognized schemas to the latest internal value, and // Servers should convert recognized schemas to the latest internal value, and
// may reject unrecognized values. // may reject unrecognized values.
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#resources // More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#resources
// +optional
optional string apiVersion = 2; optional string apiVersion = 2;
} }

View File

@ -21,7 +21,6 @@ import (
"k8s.io/client-go/pkg/labels" "k8s.io/client-go/pkg/labels"
"k8s.io/client-go/pkg/selection" "k8s.io/client-go/pkg/selection"
"k8s.io/client-go/pkg/util/sets"
) )
// LabelSelectorAsSelector converts the LabelSelector api type into a struct that implements // LabelSelectorAsSelector converts the LabelSelector api type into a struct that implements
@ -36,7 +35,7 @@ func LabelSelectorAsSelector(ps *LabelSelector) (labels.Selector, error) {
} }
selector := labels.NewSelector() selector := labels.NewSelector()
for k, v := range ps.MatchLabels { for k, v := range ps.MatchLabels {
r, err := labels.NewRequirement(k, selection.Equals, sets.NewString(v)) r, err := labels.NewRequirement(k, selection.Equals, []string{v})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -56,7 +55,7 @@ func LabelSelectorAsSelector(ps *LabelSelector) (labels.Selector, error) {
default: default:
return nil, fmt.Errorf("%q is not a valid pod selector operator", expr.Operator) return nil, fmt.Errorf("%q is not a valid pod selector operator", expr.Operator)
} }
r, err := labels.NewRequirement(expr.Key, op, sets.NewString(expr.Values...)) r, err := labels.NewRequirement(expr.Key, op, append([]string(nil), expr.Values...))
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -36,12 +36,14 @@ type TypeMeta struct {
// Cannot be updated. // Cannot be updated.
// In CamelCase. // In CamelCase.
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds // More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds
// +optional
Kind string `json:"kind,omitempty" protobuf:"bytes,1,opt,name=kind"` Kind string `json:"kind,omitempty" protobuf:"bytes,1,opt,name=kind"`
// APIVersion defines the versioned schema of this representation of an object. // APIVersion defines the versioned schema of this representation of an object.
// Servers should convert recognized schemas to the latest internal value, and // Servers should convert recognized schemas to the latest internal value, and
// may reject unrecognized values. // may reject unrecognized values.
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#resources // More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#resources
// +optional
APIVersion string `json:"apiVersion,omitempty" protobuf:"bytes,2,opt,name=apiVersion"` APIVersion string `json:"apiVersion,omitempty" protobuf:"bytes,2,opt,name=apiVersion"`
} }
@ -51,6 +53,7 @@ type ListMeta struct {
// SelfLink is a URL representing this object. // SelfLink is a URL representing this object.
// Populated by the system. // Populated by the system.
// Read-only. // Read-only.
// +optional
SelfLink string `json:"selfLink,omitempty" protobuf:"bytes,1,opt,name=selfLink"` SelfLink string `json:"selfLink,omitempty" protobuf:"bytes,1,opt,name=selfLink"`
// String that identifies the server's internal version of this object that // String that identifies the server's internal version of this object that
@ -59,6 +62,7 @@ type ListMeta struct {
// Populated by the system. // Populated by the system.
// Read-only. // Read-only.
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#concurrency-control-and-consistency // More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#concurrency-control-and-consistency
// +optional
ResourceVersion string `json:"resourceVersion,omitempty" protobuf:"bytes,2,opt,name=resourceVersion"` ResourceVersion string `json:"resourceVersion,omitempty" protobuf:"bytes,2,opt,name=resourceVersion"`
} }
@ -76,25 +80,31 @@ type Status struct {
TypeMeta `json:",inline"` TypeMeta `json:",inline"`
// Standard list metadata. // Standard list metadata.
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds // More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds
// +optional
ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Status of the operation. // Status of the operation.
// One of: "Success" or "Failure". // One of: "Success" or "Failure".
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#spec-and-status // More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#spec-and-status
// +optional
Status string `json:"status,omitempty" protobuf:"bytes,2,opt,name=status"` Status string `json:"status,omitempty" protobuf:"bytes,2,opt,name=status"`
// A human-readable description of the status of this operation. // A human-readable description of the status of this operation.
// +optional
Message string `json:"message,omitempty" protobuf:"bytes,3,opt,name=message"` Message string `json:"message,omitempty" protobuf:"bytes,3,opt,name=message"`
// A machine-readable description of why this operation is in the // A machine-readable description of why this operation is in the
// "Failure" status. If this value is empty there // "Failure" status. If this value is empty there
// is no information available. A Reason clarifies an HTTP status // is no information available. A Reason clarifies an HTTP status
// code but does not override it. // code but does not override it.
// +optional
Reason StatusReason `json:"reason,omitempty" protobuf:"bytes,4,opt,name=reason,casttype=StatusReason"` Reason StatusReason `json:"reason,omitempty" protobuf:"bytes,4,opt,name=reason,casttype=StatusReason"`
// Extended data associated with the reason. Each reason may define its // Extended data associated with the reason. Each reason may define its
// own extended details. This field is optional and the data returned // own extended details. This field is optional and the data returned
// is not guaranteed to conform to any schema except that defined by // is not guaranteed to conform to any schema except that defined by
// the reason type. // the reason type.
// +optional
Details *StatusDetails `json:"details,omitempty" protobuf:"bytes,5,opt,name=details"` Details *StatusDetails `json:"details,omitempty" protobuf:"bytes,5,opt,name=details"`
// Suggested HTTP return code for this status, 0 if not set. // Suggested HTTP return code for this status, 0 if not set.
// +optional
Code int32 `json:"code,omitempty" protobuf:"varint,6,opt,name=code"` Code int32 `json:"code,omitempty" protobuf:"varint,6,opt,name=code"`
} }
@ -107,17 +117,22 @@ type Status struct {
type StatusDetails struct { type StatusDetails struct {
// The name attribute of the resource associated with the status StatusReason // The name attribute of the resource associated with the status StatusReason
// (when there is a single name which can be described). // (when there is a single name which can be described).
// +optional
Name string `json:"name,omitempty" protobuf:"bytes,1,opt,name=name"` Name string `json:"name,omitempty" protobuf:"bytes,1,opt,name=name"`
// The group attribute of the resource associated with the status StatusReason. // The group attribute of the resource associated with the status StatusReason.
// +optional
Group string `json:"group,omitempty" protobuf:"bytes,2,opt,name=group"` Group string `json:"group,omitempty" protobuf:"bytes,2,opt,name=group"`
// The kind attribute of the resource associated with the status StatusReason. // The kind attribute of the resource associated with the status StatusReason.
// On some operations may differ from the requested resource Kind. // On some operations may differ from the requested resource Kind.
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds // More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds
// +optional
Kind string `json:"kind,omitempty" protobuf:"bytes,3,opt,name=kind"` Kind string `json:"kind,omitempty" protobuf:"bytes,3,opt,name=kind"`
// The Causes array includes more details associated with the StatusReason // The Causes array includes more details associated with the StatusReason
// failure. Not all StatusReasons may provide detailed causes. // failure. Not all StatusReasons may provide detailed causes.
// +optional
Causes []StatusCause `json:"causes,omitempty" protobuf:"bytes,4,rep,name=causes"` Causes []StatusCause `json:"causes,omitempty" protobuf:"bytes,4,rep,name=causes"`
// If specified, the time in seconds before the operation should be retried. // If specified, the time in seconds before the operation should be retried.
// +optional
RetryAfterSeconds int32 `json:"retryAfterSeconds,omitempty" protobuf:"varint,5,opt,name=retryAfterSeconds"` RetryAfterSeconds int32 `json:"retryAfterSeconds,omitempty" protobuf:"varint,5,opt,name=retryAfterSeconds"`
} }
@ -257,9 +272,11 @@ const (
type StatusCause struct { type StatusCause struct {
// A machine-readable description of the cause of the error. If this value is // A machine-readable description of the cause of the error. If this value is
// empty there is no information available. // empty there is no information available.
// +optional
Type CauseType `json:"reason,omitempty" protobuf:"bytes,1,opt,name=reason,casttype=CauseType"` Type CauseType `json:"reason,omitempty" protobuf:"bytes,1,opt,name=reason,casttype=CauseType"`
// A human-readable description of the cause of the error. This field may be // A human-readable description of the cause of the error. This field may be
// presented as-is to a reader. // presented as-is to a reader.
// +optional
Message string `json:"message,omitempty" protobuf:"bytes,2,opt,name=message"` Message string `json:"message,omitempty" protobuf:"bytes,2,opt,name=message"`
// The field of the resource that has caused this error, as named by its JSON // The field of the resource that has caused this error, as named by its JSON
// serialization. May include dot and postfix notation for nested attributes. // serialization. May include dot and postfix notation for nested attributes.
@ -270,6 +287,7 @@ type StatusCause struct {
// Examples: // Examples:
// "name" - the field "name" on the current resource // "name" - the field "name" on the current resource
// "items[0].name" - the field "name" on the first array entry in "items" // "items[0].name" - the field "name" on the first array entry in "items"
// +optional
Field string `json:"field,omitempty" protobuf:"bytes,3,opt,name=field"` Field string `json:"field,omitempty" protobuf:"bytes,3,opt,name=field"`
} }
@ -336,6 +354,7 @@ type APIGroup struct {
Versions []GroupVersionForDiscovery `json:"versions" protobuf:"bytes,2,rep,name=versions"` Versions []GroupVersionForDiscovery `json:"versions" protobuf:"bytes,2,rep,name=versions"`
// preferredVersion is the version preferred by the API server, which // preferredVersion is the version preferred by the API server, which
// probably is the storage version. // probably is the storage version.
// +optional
PreferredVersion GroupVersionForDiscovery `json:"preferredVersion,omitempty" protobuf:"bytes,3,opt,name=preferredVersion"` PreferredVersion GroupVersionForDiscovery `json:"preferredVersion,omitempty" protobuf:"bytes,3,opt,name=preferredVersion"`
// a map of client CIDR to server address that is serving this group. // a map of client CIDR to server address that is serving this group.
// This is to help clients reach servers in the most network-efficient way possible. // This is to help clients reach servers in the most network-efficient way possible.
@ -429,8 +448,10 @@ type LabelSelector struct {
// matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels // matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
// map is equivalent to an element of matchExpressions, whose key field is "key", the // map is equivalent to an element of matchExpressions, whose key field is "key", the
// operator is "In", and the values array contains only "value". The requirements are ANDed. // operator is "In", and the values array contains only "value". The requirements are ANDed.
// +optional
MatchLabels map[string]string `json:"matchLabels,omitempty" protobuf:"bytes,1,rep,name=matchLabels"` MatchLabels map[string]string `json:"matchLabels,omitempty" protobuf:"bytes,1,rep,name=matchLabels"`
// matchExpressions is a list of label selector requirements. The requirements are ANDed. // matchExpressions is a list of label selector requirements. The requirements are ANDed.
// +optional
MatchExpressions []LabelSelectorRequirement `json:"matchExpressions,omitempty" protobuf:"bytes,2,rep,name=matchExpressions"` MatchExpressions []LabelSelectorRequirement `json:"matchExpressions,omitempty" protobuf:"bytes,2,rep,name=matchExpressions"`
} }
@ -446,6 +467,7 @@ type LabelSelectorRequirement struct {
// the values array must be non-empty. If the operator is Exists or DoesNotExist, // the values array must be non-empty. If the operator is Exists or DoesNotExist,
// the values array must be empty. This array is replaced during a strategic // the values array must be empty. This array is replaced during a strategic
// merge patch. // merge patch.
// +optional
Values []string `json:"values,omitempty" protobuf:"bytes,3,rep,name=values"` Values []string `json:"values,omitempty" protobuf:"bytes,3,rep,name=values"`
} }

View File

@ -269,12 +269,6 @@ func addConversionFuncs(scheme *runtime.Scheme) error {
} }
func Convert_v1_ReplicationController_to_extensions_ReplicaSet(in *ReplicationController, out *extensions.ReplicaSet, s conversion.Scope) error { func Convert_v1_ReplicationController_to_extensions_ReplicaSet(in *ReplicationController, out *extensions.ReplicaSet, s conversion.Scope) error {
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
defaulting.(func(*ReplicationController))(in)
}
if err := api.Convert_unversioned_TypeMeta_To_unversioned_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
return err
}
if err := Convert_v1_ObjectMeta_To_api_ObjectMeta(&in.ObjectMeta, &out.ObjectMeta, s); err != nil { if err := Convert_v1_ObjectMeta_To_api_ObjectMeta(&in.ObjectMeta, &out.ObjectMeta, s); err != nil {
return err return err
} }
@ -288,9 +282,6 @@ func Convert_v1_ReplicationController_to_extensions_ReplicaSet(in *ReplicationCo
} }
func Convert_v1_ReplicationControllerSpec_to_extensions_ReplicaSetSpec(in *ReplicationControllerSpec, out *extensions.ReplicaSetSpec, s conversion.Scope) error { func Convert_v1_ReplicationControllerSpec_to_extensions_ReplicaSetSpec(in *ReplicationControllerSpec, out *extensions.ReplicaSetSpec, s conversion.Scope) error {
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
defaulting.(func(*ReplicationControllerSpec))(in)
}
out.Replicas = *in.Replicas out.Replicas = *in.Replicas
if in.Selector != nil { if in.Selector != nil {
api.Convert_map_to_unversioned_LabelSelector(&in.Selector, out.Selector, s) api.Convert_map_to_unversioned_LabelSelector(&in.Selector, out.Selector, s)
@ -304,9 +295,6 @@ func Convert_v1_ReplicationControllerSpec_to_extensions_ReplicaSetSpec(in *Repli
} }
func Convert_v1_ReplicationControllerStatus_to_extensions_ReplicaSetStatus(in *ReplicationControllerStatus, out *extensions.ReplicaSetStatus, s conversion.Scope) error { func Convert_v1_ReplicationControllerStatus_to_extensions_ReplicaSetStatus(in *ReplicationControllerStatus, out *extensions.ReplicaSetStatus, s conversion.Scope) error {
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
defaulting.(func(*ReplicationControllerStatus))(in)
}
out.Replicas = in.Replicas out.Replicas = in.Replicas
out.FullyLabeledReplicas = in.FullyLabeledReplicas out.FullyLabeledReplicas = in.FullyLabeledReplicas
out.ReadyReplicas = in.ReadyReplicas out.ReadyReplicas = in.ReadyReplicas
@ -316,12 +304,6 @@ func Convert_v1_ReplicationControllerStatus_to_extensions_ReplicaSetStatus(in *R
} }
func Convert_extensions_ReplicaSet_to_v1_ReplicationController(in *extensions.ReplicaSet, out *ReplicationController, s conversion.Scope) error { func Convert_extensions_ReplicaSet_to_v1_ReplicationController(in *extensions.ReplicaSet, out *ReplicationController, s conversion.Scope) error {
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
defaulting.(func(*extensions.ReplicaSet))(in)
}
if err := api.Convert_unversioned_TypeMeta_To_unversioned_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
return err
}
if err := Convert_api_ObjectMeta_To_v1_ObjectMeta(&in.ObjectMeta, &out.ObjectMeta, s); err != nil { if err := Convert_api_ObjectMeta_To_v1_ObjectMeta(&in.ObjectMeta, &out.ObjectMeta, s); err != nil {
return err return err
} }
@ -342,9 +324,6 @@ func Convert_extensions_ReplicaSet_to_v1_ReplicationController(in *extensions.Re
} }
func Convert_extensions_ReplicaSetSpec_to_v1_ReplicationControllerSpec(in *extensions.ReplicaSetSpec, out *ReplicationControllerSpec, s conversion.Scope) error { func Convert_extensions_ReplicaSetSpec_to_v1_ReplicationControllerSpec(in *extensions.ReplicaSetSpec, out *ReplicationControllerSpec, s conversion.Scope) error {
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
defaulting.(func(*extensions.ReplicaSetSpec))(in)
}
out.Replicas = new(int32) out.Replicas = new(int32)
*out.Replicas = in.Replicas *out.Replicas = in.Replicas
out.MinReadySeconds = in.MinReadySeconds out.MinReadySeconds = in.MinReadySeconds
@ -360,9 +339,6 @@ func Convert_extensions_ReplicaSetSpec_to_v1_ReplicationControllerSpec(in *exten
} }
func Convert_extensions_ReplicaSetStatus_to_v1_ReplicationControllerStatus(in *extensions.ReplicaSetStatus, out *ReplicationControllerStatus, s conversion.Scope) error { func Convert_extensions_ReplicaSetStatus_to_v1_ReplicationControllerStatus(in *extensions.ReplicaSetStatus, out *ReplicationControllerStatus, s conversion.Scope) error {
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
defaulting.(func(*extensions.ReplicaSetStatus))(in)
}
out.Replicas = in.Replicas out.Replicas = in.Replicas
out.FullyLabeledReplicas = in.FullyLabeledReplicas out.FullyLabeledReplicas = in.FullyLabeledReplicas
out.ReadyReplicas = in.ReadyReplicas out.ReadyReplicas = in.ReadyReplicas
@ -387,7 +363,9 @@ func Convert_api_ReplicationControllerSpec_To_v1_ReplicationControllerSpec(in *a
} }
func Convert_v1_ReplicationControllerSpec_To_api_ReplicationControllerSpec(in *ReplicationControllerSpec, out *api.ReplicationControllerSpec, s conversion.Scope) error { func Convert_v1_ReplicationControllerSpec_To_api_ReplicationControllerSpec(in *ReplicationControllerSpec, out *api.ReplicationControllerSpec, s conversion.Scope) error {
out.Replicas = *in.Replicas if in.Replicas != nil {
out.Replicas = *in.Replicas
}
out.MinReadySeconds = in.MinReadySeconds out.MinReadySeconds = in.MinReadySeconds
out.Selector = in.Selector out.Selector = in.Selector
if in.Template != nil { if in.Template != nil {
@ -644,6 +622,11 @@ func Convert_v1_Pod_To_api_Pod(in *Pod, out *api.Pod, s conversion.Scope) error
// taking responsibility to ensure mutation of in is not exposed // taking responsibility to ensure mutation of in is not exposed
// back to the caller. // back to the caller.
in.Spec.InitContainers = values in.Spec.InitContainers = values
// Call defaulters explicitly until annotations are removed
for i := range in.Spec.InitContainers {
c := &in.Spec.InitContainers[i]
SetDefaults_Container(c)
}
} }
// If there is a beta annotation, copy to alpha key. // If there is a beta annotation, copy to alpha key.
// See commit log for PR #31026 for why we do this. // See commit log for PR #31026 for why we do this.
@ -751,19 +734,20 @@ func Convert_v1_PodSecurityContext_To_api_PodSecurityContext(in *PodSecurityCont
return nil return nil
} }
// +k8s:conversion-fn=copy-only
func Convert_v1_ResourceList_To_api_ResourceList(in *ResourceList, out *api.ResourceList, s conversion.Scope) error { func Convert_v1_ResourceList_To_api_ResourceList(in *ResourceList, out *api.ResourceList, s conversion.Scope) error {
if *in == nil { if *in == nil {
return nil return nil
} }
if *out == nil { if *out == nil {
*out = make(api.ResourceList, len(*in)) *out = make(api.ResourceList, len(*in))
} }
for key, val := range *in { for key, val := range *in {
// Moved to defaults
// TODO(#18538): We round up resource values to milli scale to maintain API compatibility. // TODO(#18538): We round up resource values to milli scale to maintain API compatibility.
// In the future, we should instead reject values that need rounding. // In the future, we should instead reject values that need rounding.
const milliScale = -3 // const milliScale = -3
val.RoundUp(milliScale) // val.RoundUp(milliScale)
(*out)[api.ResourceName(key)] = val (*out)[api.ResourceName(key)] = val
} }

Some files were not shown because too many files have changed in this diff Show More