diff --git a/.travis.yml b/.travis.yml
index c76c36f9c..ebfbc6542 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -20,7 +20,7 @@ before_script:
- helm lint helm/botkube
script:
- - make unit-test
+ - make test
- make
after_success:
diff --git a/Makefile b/Makefile
index 497d3a569..d9f39aec6 100644
--- a/Makefile
+++ b/Makefile
@@ -2,11 +2,11 @@ IMAGE_REPO=infracloud/botkube
TAG=$(shell cut -d'=' -f2- .release)
.DEFAULT_GOAL := build
-.PHONY: release git-tag check-git-status build container-image pre-build tag-image publish unit-test system-check
+.PHONY: release git-tag check-git-status build container-image pre-build tag-image publish test system-check
#Docker Tasks
#Make a release
-release: check-git-status unit-test container-image tag-image publish git-tag
+release: check-git-status test container-image tag-image publish git-tag
@echo "Successfully releeased version $(TAG)"
#Create a git tag
@@ -25,10 +25,10 @@ check-git-status:
@if [ -z "$(shell git remote -v)" ] ; then echo 'ERROR: No remote to push tags to' && exit 1 ; fi
@if [ -z "$(shell git config user.email)" ] ; then echo 'ERROR: Unable to detect git credentials' && exit 1 ; fi
-# unit-test
-unit-test: system-check
- @echo "Starting unit tests"
- @./hack/unit-test.sh -v
+# test
+test: system-check
+ @echo "Starting unit and integration tests"
+ @./hack/runtests.sh
#Build the binary
build: pre-build
diff --git a/cmd/botkube/main.go b/cmd/botkube/main.go
index 5b3b0763f..c2099d707 100644
--- a/cmd/botkube/main.go
+++ b/cmd/botkube/main.go
@@ -7,6 +7,7 @@ import (
"github.com/infracloudio/botkube/pkg/config"
"github.com/infracloudio/botkube/pkg/controller"
log "github.com/infracloudio/botkube/pkg/logging"
+ "github.com/infracloudio/botkube/pkg/notify"
"github.com/infracloudio/botkube/pkg/utils"
)
@@ -29,14 +30,27 @@ func main() {
go mb.Start()
}
+ // List notifiers
+ var notifiers []notify.Notifier
+ if Config.Communications.Slack.Enabled {
+ notifiers = append(notifiers, notify.NewSlack(Config))
+ }
+ if Config.Communications.Mattermost.Enabled {
+ if notifier, err := notify.NewMattermost(Config); err == nil {
+ notifiers = append(notifiers, notifier)
+ }
+ }
+ if Config.Communications.ElasticSearch.Enabled {
+ notifiers = append(notifiers, notify.NewElasticSearch(Config))
+ }
+
if Config.Settings.UpgradeNotifier {
log.Logger.Info("Starting upgrade notifier")
- go controller.UpgradeNotifier(Config)
-
+ go controller.UpgradeNotifier(Config, notifiers)
}
// Init KubeClient, InformerMap and start controller
utils.InitKubeClient()
utils.InitInformerMap()
- controller.RegisterInformers(Config)
+ controller.RegisterInformers(Config, notifiers)
}
diff --git a/go.mod b/go.mod
index 8aa28a106..6bb8f5b99 100644
--- a/go.mod
+++ b/go.mod
@@ -28,12 +28,13 @@ require (
github.com/mattermost/mattermost-server v5.11.1+incompatible
github.com/mattn/go-sqlite3 v1.11.0 // indirect
github.com/nicksnyder/go-i18n v1.10.1 // indirect
- github.com/nlopes/slack v0.4.0
+ github.com/nlopes/slack v0.5.1-0.20190623232825-2891986e2a3e
github.com/olivere/elastic v6.2.21+incompatible
github.com/pborman/uuid v1.2.0 // indirect
github.com/pkg/errors v0.8.1 // indirect
github.com/sirupsen/logrus v1.4.2
github.com/stretchr/objx v0.2.0 // indirect
+ github.com/stretchr/testify v1.3.0
github.com/ziutek/mymysql v1.5.4 // indirect
go.uber.org/atomic v1.4.0 // indirect
go.uber.org/multierr v1.1.0 // indirect
diff --git a/go.sum b/go.sum
index 6d9961260..77352eeaa 100644
--- a/go.sum
+++ b/go.sum
@@ -20,6 +20,7 @@ github.com/dyatlov/go-opengraph v0.0.0-20180429202543-816b6608b3c8/go.mod h1:nYi
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
+github.com/evanphx/json-patch v4.2.0+incompatible h1:fUDGZCv/7iAN7u0puUVhvKCcsR6vRfwrJatElLBEf0I=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
@@ -68,6 +69,7 @@ github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsC
github.com/googleapis/gnostic v0.3.0 h1:CcQijm0XKekKjP/YCz28LXVSpgguuB+nCxaSjCe09y0=
github.com/googleapis/gnostic v0.3.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4=
+github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
@@ -125,6 +127,8 @@ github.com/nicksnyder/go-i18n v1.10.1 h1:isfg77E/aCD7+0lD/D00ebR2MV5vgeQ276WYyDa
github.com/nicksnyder/go-i18n v1.10.1/go.mod h1:e4Di5xjP9oTVrC6y3C7C0HoSYXjSbhh/dU0eUV32nB4=
github.com/nlopes/slack v0.4.0 h1:OVnHm7lv5gGT5gkcHsZAyw++oHVFihbjWbL3UceUpiA=
github.com/nlopes/slack v0.4.0/go.mod h1:jVI4BBK3lSktibKahxBF74txcK2vyvkza1z/+rRnVAM=
+github.com/nlopes/slack v0.5.1-0.20190623232825-2891986e2a3e h1:4X/3/ywN6f+XITaDoI9GjXbF7MHk7fuunXsEWZX1GLc=
+github.com/nlopes/slack v0.5.1-0.20190623232825-2891986e2a3e/go.mod h1:JzQ9m3PMAqcpeCam7UaHSuBuupz7CmpjehYMayT6YOk=
github.com/olivere/elastic v6.2.21+incompatible h1:QnTuofzxOCV5FrYLywjkMxOmOWhAeild1VXxKRksK9Y=
github.com/olivere/elastic v6.2.21+incompatible/go.mod h1:J+q1zQJTgAz9woqsbVRqGeB5G1iqDKVBWLNSYW8yfJ8=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@@ -140,6 +144,7 @@ github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtP
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
+github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -251,6 +256,7 @@ k8s.io/klog v0.3.1/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v0.3.3 h1:niceAagH1tzskmaie/icWd7ci1wbG7Bf2c6YGcQv+3c=
k8s.io/klog v0.3.3/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc=
+k8s.io/kube-openapi v0.0.0-20190709113604-33be087ad058 h1:di3XCwddOR9cWBNpfgXaskhh6cgJuwcK54rvtwUaC10=
k8s.io/kube-openapi v0.0.0-20190709113604-33be087ad058/go.mod h1:nfDlWeOsu3pUf4yWGL+ERqohP4YsZcBJXWMK+gkzOA4=
k8s.io/utils v0.0.0-20190221042446-c2654d5206da/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0=
k8s.io/utils v0.0.0-20190801114015-581e00157fb1 h1:+ySTxfHnfzZb9ys375PXNlLhkJPLKgHajBU0N62BDvE=
diff --git a/hack/unit-test.sh b/hack/runtests.sh
similarity index 53%
rename from hack/unit-test.sh
rename to hack/runtests.sh
index 3146a95a9..d71fa0f2a 100755
--- a/hack/unit-test.sh
+++ b/hack/runtests.sh
@@ -4,8 +4,10 @@ set -o errexit
set -o nounset
set -o pipefail
-PACKAGES=$(go list ./... | grep -v '/vendor/')
+export CONFIG_PATH=`pwd`
+# Run unit and integration tests excluding dependencies
+PACKAGES=$(go list ./... | grep -v '/vendor/')
for package in $PACKAGES; do
- go test ${@} "$package"
+ go test -tags=test ${@} "$package" -v
done
diff --git a/pkg/bot/mattermost.go b/pkg/bot/mattermost.go
index da6a8664d..8df5d93a4 100644
--- a/pkg/bot/mattermost.go
+++ b/pkg/bot/mattermost.go
@@ -31,8 +31,8 @@ const (
WebSocketSecureProtocol = "wss://"
)
-// mmBot listens for user's message, execute commands and sends back the response
-type mmBot struct {
+// MMBot listens for user's message, execute commands and sends back the response
+type MMBot struct {
ServerURL string
Token string
TeamName string
@@ -56,7 +56,7 @@ func NewMattermostBot() Bot {
logging.Logger.Fatal(fmt.Sprintf("Error in loading configuration. Error:%s", err.Error()))
}
- return &mmBot{
+ return &MMBot{
ServerURL: c.Communications.Mattermost.URL,
Token: c.Communications.Mattermost.Token,
TeamName: c.Communications.Mattermost.Team,
@@ -67,7 +67,7 @@ func NewMattermostBot() Bot {
}
// Start establishes mattermost connection and listens for messages
-func (b *mmBot) Start() {
+func (b *MMBot) Start() {
client = model.NewAPIv4Client(b.ServerURL)
client.SetOAuthToken(b.Token)
@@ -121,7 +121,7 @@ func (b *mmBot) Start() {
}
// Check incomming message and take action
-func (mm *mattermostMessage) handleMessage(b *mmBot) {
+func (mm *mattermostMessage) handleMessage(b *MMBot) {
post := model.PostFromJson(strings.NewReader(mm.Event.Data["post"].(string)))
channelType := mmChannelType(mm.Event.Data["channel_type"].(string))
if channelType == mmChannelPrivate || channelType == mmChannelPublic {
@@ -179,7 +179,7 @@ func checkServerConnection() error {
}
// Check if team exists in Mattermost
-func (b *mmBot) getTeam() *model.Team {
+func (b *MMBot) getTeam() *model.Team {
botTeam, resp := client.GetTeamByName(b.TeamName, "")
if resp.Error != nil {
logging.Logger.Fatal("There was a problem finding Mattermost team ", b.TeamName, "\nError: ", resp.Error)
@@ -188,7 +188,7 @@ func (b *mmBot) getTeam() *model.Team {
}
// Check if botkube user exists in Mattermost
-func (b *mmBot) getUser() *model.User {
+func (b *MMBot) getUser() *model.User {
users, resp := client.AutocompleteUsersInTeam(b.getTeam().Id, BotName, 1, "")
if resp.Error != nil {
logging.Logger.Fatal("There was a problem finding Mattermost user ", BotName, "\nError: ", resp.Error)
@@ -197,7 +197,7 @@ func (b *mmBot) getUser() *model.User {
}
// Create channel if not present and add botkube user in channel
-func (b *mmBot) getChannel() *model.Channel {
+func (b *MMBot) getChannel() *model.Channel {
// Checking if channel exists
botChannel, resp := client.GetChannelByName(b.ChannelName, b.getTeam().Id, "")
if resp.Error != nil {
diff --git a/pkg/bot/slack.go b/pkg/bot/slack.go
index 202a9ad24..383b9412b 100644
--- a/pkg/bot/slack.go
+++ b/pkg/bot/slack.go
@@ -10,12 +10,14 @@ import (
"github.com/nlopes/slack"
)
-// slackBot listens for user's message, execute commands and sends back the response
-type slackBot struct {
+// SlackBot listens for user's message, execute commands and sends back the response
+type SlackBot struct {
Token string
AllowKubectl bool
ClusterName string
ChannelName string
+ SlackURL string
+ BotID string
}
// slackMessage contains message details to execute command and send back the result
@@ -26,6 +28,7 @@ type slackMessage struct {
Response string
IsAuthChannel bool
RTM *slack.RTM
+ SlackClient *slack.Client
}
// NewSlackBot returns new Bot object
@@ -34,7 +37,7 @@ func NewSlackBot() Bot {
if err != nil {
logging.Logger.Fatal(fmt.Sprintf("Error in loading configuration. Error:%s", err.Error()))
}
- return &slackBot{
+ return &SlackBot{
Token: c.Communications.Slack.Token,
AllowKubectl: c.Settings.AllowKubectl,
ClusterName: c.Settings.ClusterName,
@@ -43,18 +46,24 @@ func NewSlackBot() Bot {
}
// Start starts the slacknot RTM connection and listens for messages
-func (b *slackBot) Start() {
+func (b *SlackBot) Start() {
+ var botID string
api := slack.New(b.Token)
- authResp, err := api.AuthTest()
- if err != nil {
- logging.Logger.Fatal(err)
+ if len(b.SlackURL) != 0 {
+ api = slack.New(b.Token, slack.OptionAPIURL(b.SlackURL))
+ botID = b.BotID
+ } else {
+ authResp, err := api.AuthTest()
+ if err != nil {
+ logging.Logger.Fatal(err)
+ }
+ botID = authResp.UserID
}
- botID := authResp.UserID
- rtm := api.NewRTM()
- go rtm.ManageConnection()
+ RTM := api.NewRTM()
+ go RTM.ManageConnection()
- for msg := range rtm.IncomingEvents {
+ for msg := range RTM.IncomingEvents {
switch ev := msg.Data.(type) {
case *slack.ConnectedEvent:
logging.Logger.Debug("Connection Info: ", ev.Info)
@@ -65,9 +74,10 @@ func (b *slackBot) Start() {
continue
}
sm := slackMessage{
- Event: ev,
- BotID: botID,
- RTM: rtm,
+ Event: ev,
+ BotID: botID,
+ RTM: RTM,
+ SlackClient: api,
}
sm.HandleMessage(b)
@@ -82,10 +92,11 @@ func (b *slackBot) Start() {
}
}
-func (sm *slackMessage) HandleMessage(b *slackBot) {
+func (sm *slackMessage) HandleMessage(b *SlackBot) {
logging.Logger.Debugf("Slack incoming message: %+v", sm.Event)
+
// Check if message posted in authenticated channel
- info, err := slack.New(b.Token).GetConversationInfo(sm.Event.Channel, true)
+ info, err := sm.SlackClient.GetConversationInfo(sm.Event.Channel, true)
if err == nil {
if info.IsChannel || info.IsPrivate {
// Message posted in a channel
@@ -99,9 +110,16 @@ func (sm *slackMessage) HandleMessage(b *slackBot) {
}
}
}
+ // Serve only if current channel is in config
+ if b.ChannelName == sm.Event.Channel {
+ sm.IsAuthChannel = true
+ }
// Trim the @BotKube prefix
sm.Request = strings.TrimPrefix(sm.Event.Text, "<@"+sm.BotID+"> ")
+ if len(sm.Request) == 0 {
+ return
+ }
e := execute.NewDefaultExecutor(sm.Request, b.AllowKubectl, b.ClusterName, b.ChannelName, sm.IsAuthChannel)
sm.Response = e.Execute()
@@ -126,10 +144,7 @@ func (sm slackMessage) Send() {
return
}
- params := slack.PostMessageParameters{
- AsUser: true,
- }
- if _, _, err := sm.RTM.PostMessage(sm.Event.Channel, "```"+sm.Response+"```", params); err != nil {
+ if _, _, err := sm.RTM.PostMessage(sm.Event.Channel, slack.MsgOptionText("```"+sm.Response+"```", false), slack.MsgOptionAsUser(true)); err != nil {
logging.Logger.Error("Error in sending message:", err)
}
}
diff --git a/pkg/controller/controller.go b/pkg/controller/controller.go
index 58d6478a3..764926999 100644
--- a/pkg/controller/controller.go
+++ b/pkg/controller/controller.go
@@ -33,13 +33,13 @@ const (
var startTime time.Time
// RegisterInformers creates new informer controllers to watch k8s resources
-func RegisterInformers(c *config.Config) {
- sendMessage(c, fmt.Sprintf(controllerStartMsg, c.Settings.ClusterName))
+func RegisterInformers(c *config.Config, notifiers []notify.Notifier) {
+ sendMessage(c, notifiers, fmt.Sprintf(controllerStartMsg, c.Settings.ClusterName))
startTime = time.Now()
// Start config file watcher if enabled
if c.Settings.ConfigWatcher {
- go configWatcher(c)
+ go configWatcher(c, notifiers)
}
// Register informers for resource lifecycle events
@@ -50,7 +50,7 @@ func RegisterInformers(c *config.Config) {
continue
}
log.Logger.Infof("Adding informer for resource:%s", r.Name)
- utils.ResourceInformerMap[r.Name].AddEventHandler(registerEventHandlers(c, r.Name, r.Events))
+ utils.ResourceInformerMap[r.Name].AddEventHandler(registerEventHandlers(c, notifiers, r.Name, r.Events))
}
}
@@ -76,10 +76,10 @@ func RegisterInformers(c *config.Config) {
switch strings.ToLower(eventObj.Type) {
case config.WarningEvent.String():
// Send WarningEvent as ErrorEvents
- sendEvent(obj, nil, c, kind, config.ErrorEvent)
+ sendEvent(obj, nil, c, notifiers, kind, config.ErrorEvent)
case config.NormalEvent.String():
// Send NormalEvent as Insignificant InfoEvent
- sendEvent(obj, nil, c, kind, config.InfoEvent)
+ sendEvent(obj, nil, c, notifiers, kind, config.InfoEvent)
}
},
})
@@ -93,36 +93,36 @@ func RegisterInformers(c *config.Config) {
signal.Notify(sigterm, syscall.SIGTERM)
signal.Notify(sigterm, syscall.SIGINT)
<-sigterm
- sendMessage(c, fmt.Sprintf(controllerStopMsg, c.Settings.ClusterName))
+ sendMessage(c, notifiers, fmt.Sprintf(controllerStopMsg, c.Settings.ClusterName))
}
-func registerEventHandlers(c *config.Config, resourceType string, events []config.EventType) (handlerFns cache.ResourceEventHandlerFuncs) {
+func registerEventHandlers(c *config.Config, notifiers []notify.Notifier, resourceType string, events []config.EventType) (handlerFns cache.ResourceEventHandlerFuncs) {
for _, event := range events {
if event == config.AllEvent || event == config.CreateEvent {
handlerFns.AddFunc = func(obj interface{}) {
log.Logger.Debugf("Processing add to %v", resourceType)
- sendEvent(obj, nil, c, resourceType, config.CreateEvent)
+ sendEvent(obj, nil, c, notifiers, resourceType, config.CreateEvent)
}
}
if event == config.AllEvent || event == config.UpdateEvent {
handlerFns.UpdateFunc = func(old, new interface{}) {
log.Logger.Debugf("Processing update to %v\n Object: %+v\n", resourceType, new)
- sendEvent(new, old, c, resourceType, config.UpdateEvent)
+ sendEvent(new, old, c, notifiers, resourceType, config.UpdateEvent)
}
}
if event == config.AllEvent || event == config.DeleteEvent {
handlerFns.DeleteFunc = func(obj interface{}) {
log.Logger.Debugf("Processing delete to %v", resourceType)
- sendEvent(obj, nil, c, resourceType, config.DeleteEvent)
+ sendEvent(obj, nil, c, notifiers, resourceType, config.DeleteEvent)
}
}
}
return handlerFns
}
-func sendEvent(obj, oldObj interface{}, c *config.Config, kind string, eventType config.EventType) {
+func sendEvent(obj, oldObj interface{}, c *config.Config, notifiers []notify.Notifier, kind string, eventType config.EventType) {
// Filter namespaces
objectMeta := utils.GetObjectMetaData(obj)
@@ -197,42 +197,25 @@ func sendEvent(obj, oldObj interface{}, c *config.Config, kind string, eventType
log.Logger.Debug("Skipping Recommendations in Event Notifications")
}
- var notifier notify.Notifier
- // Send notification to communication channel
- if c.Communications.Slack.Enabled {
- notifier = notify.NewSlack(c)
- go notifier.SendEvent(event)
- }
-
- if c.Communications.ElasticSearch.Enabled {
- notifier = notify.NewElasticSearch(c)
- go notifier.SendEvent(event)
- }
-
- if c.Communications.Mattermost.Enabled {
- if notifier, err := notify.NewMattermost(c); err == nil {
- go notifier.SendEvent(event)
- }
+ // Send event over notifiers
+ for _, n := range notifiers {
+ go n.SendEvent(event)
}
}
-func sendMessage(c *config.Config, msg string) {
+func sendMessage(c *config.Config, notifiers []notify.Notifier, msg string) {
if len(msg) <= 0 {
log.Logger.Warn("sendMessage received string with length 0. Hence skipping.")
return
}
- if c.Communications.Slack.Enabled {
- notifier := notify.NewSlack(c)
- go notifier.SendMessage(msg)
- }
- if c.Communications.Mattermost.Enabled {
- if notifier, err := notify.NewMattermost(c); err == nil {
- go notifier.SendMessage(msg)
- }
+
+ // Send message over notifiers
+ for _, n := range notifiers {
+ go n.SendMessage(msg)
}
}
-func configWatcher(c *config.Config) {
+func configWatcher(c *config.Config, notifiers []notify.Notifier) {
configPath := os.Getenv("CONFIG_PATH")
configFile := filepath.Join(configPath, config.ConfigFileName)
@@ -269,7 +252,7 @@ func configWatcher(c *config.Config) {
return
}
<-done
- sendMessage(c, fmt.Sprintf(configUpdateMsg, c.Settings.ClusterName))
+ sendMessage(c, notifiers, fmt.Sprintf(configUpdateMsg, c.Settings.ClusterName))
// Wait for Notifier to send message
time.Sleep(5 * time.Second)
os.Exit(0)
diff --git a/pkg/controller/upgrade.go b/pkg/controller/upgrade.go
index 04e4e260a..35358b408 100644
--- a/pkg/controller/upgrade.go
+++ b/pkg/controller/upgrade.go
@@ -9,6 +9,7 @@ import (
"github.com/google/go-github/v27/github"
"github.com/infracloudio/botkube/pkg/config"
log "github.com/infracloudio/botkube/pkg/logging"
+ "github.com/infracloudio/botkube/pkg/notify"
)
var (
@@ -17,7 +18,7 @@ var (
"Visit botkube.io for more info."
)
-func checkRelease(c *config.Config) {
+func checkRelease(c *config.Config, notifiers []notify.Notifier) {
ctx := context.Background()
client := github.NewClient(nil)
release, _, err := client.Repositories.GetLatestRelease(ctx, "infracloudio", "botkube")
@@ -29,16 +30,16 @@ func checkRelease(c *config.Config) {
// Send notification if newer version available
if len(os.Getenv("BOTKUBE_VERSION")) > 0 && os.Getenv("BOTKUBE_VERSION") != *release.TagName {
- sendMessage(c, fmt.Sprintf(botkubeUpgradeMsg, *release.TagName))
+ sendMessage(c, notifiers, fmt.Sprintf(botkubeUpgradeMsg, *release.TagName))
notified = true
}
}
}
// UpgradeNotifier checks if newer version for BotKube backend available and notifies user
-func UpgradeNotifier(c *config.Config) {
+func UpgradeNotifier(c *config.Config, notifiers []notify.Notifier) {
// Check at startup
- checkRelease(c)
+ checkRelease(c, notifiers)
ticker := time.NewTicker(24 * time.Hour)
defer ticker.Stop()
@@ -49,7 +50,7 @@ func UpgradeNotifier(c *config.Config) {
return
}
// Check periodically
- checkRelease(c)
+ checkRelease(c, notifiers)
}
}
}
diff --git a/pkg/events/events.go b/pkg/events/events.go
index 1116d16d6..87ad7f014 100644
--- a/pkg/events/events.go
+++ b/pkg/events/events.go
@@ -49,6 +49,7 @@ type Event struct {
Skip bool `json:",omitempty"`
Recommendations []string
+ Warnings []string
}
// LevelMap is a map of event type to Level
@@ -172,9 +173,16 @@ func (event *Event) Message() (msg string) {
if len(event.Recommendations) > 0 {
recommend := ""
for _, m := range event.Recommendations {
- recommend = recommend + m
+ recommend = recommend + "- " + m
}
- message = message + fmt.Sprintf("\nRecommendations: %s", recommend)
+ message = message + fmt.Sprintf("Recommendations:\n%s", recommend)
+ }
+ if len(event.Warnings) > 0 {
+ warning := ""
+ for _, m := range event.Warnings {
+ warning = warning + "- " + m
+ }
+ message = message + fmt.Sprintf("Warnings:\n%s", warning)
}
switch event.Type {
diff --git a/pkg/execute/default_executor.go b/pkg/execute/default_executor.go
new file mode 100644
index 000000000..1c520a776
--- /dev/null
+++ b/pkg/execute/default_executor.go
@@ -0,0 +1,28 @@
+// +build !test
+
+package execute
+
+import (
+ "os/exec"
+)
+
+// DefaultRunner contains default implementation for Run
+type DefaultRunner struct {
+ command string
+ args []string
+}
+
+// NewCommandRunner returns new DefaultRunner
+func NewCommandRunner(command string, args []string) CommandRunner {
+ return DefaultRunner{
+ command: command,
+ args: args,
+ }
+}
+
+// Run executes bash command
+func (r DefaultRunner) Run() (string, error) {
+ cmd := exec.Command(r.command, r.args...)
+ out, err := cmd.CombinedOutput()
+ return string(out), err
+}
diff --git a/pkg/execute/executor.go b/pkg/execute/executor.go
index f37a7b09d..4e24e240f 100644
--- a/pkg/execute/executor.go
+++ b/pkg/execute/executor.go
@@ -5,7 +5,6 @@ import (
"fmt"
"io/ioutil"
"os"
- "os/exec"
"path/filepath"
"reflect"
"strings"
@@ -76,6 +75,11 @@ type DefaultExecutor struct {
IsAuthChannel bool
}
+// CommandRunner is an interface to run bash commands
+type CommandRunner interface {
+ Run() (string, error)
+}
+
// NotifierAction creates custom type for notifier actions
type NotifierAction string
@@ -217,13 +221,15 @@ func runKubectlCommand(args []string, clusterName string, isAuthChannel bool) st
if isAuthChannel == false {
return ""
}
- cmd := exec.Command(kubectlBinary, finalArgs...)
- out, err := cmd.CombinedOutput()
+
+ // Get command runner
+ runner := NewCommandRunner(kubectlBinary, finalArgs)
+ out, err := runner.Run()
if err != nil {
log.Logger.Error("Error in executing kubectl command: ", err)
- return fmt.Sprintf("Cluster: %s\n%s", clusterName, string(out)+err.Error())
+ return fmt.Sprintf("Cluster: %s\n%s", clusterName, out+err.Error())
}
- return fmt.Sprintf("Cluster: %s\n%s", clusterName, string(out))
+ return fmt.Sprintf("Cluster: %s\n%s", clusterName, out)
}
// TODO: Have a seperate cli which runs bot commands
@@ -316,12 +322,12 @@ func makeFiltersList() string {
func findBotKubeVersion() (versions string) {
args := []string{"-c", fmt.Sprintf("%s version --short=true | grep Server", kubectlBinary)}
- cmd := exec.Command("sh", args...)
+ runner := NewCommandRunner("sh", args)
// Returns "Server Version: xxxx"
- k8sVersion, err := cmd.CombinedOutput()
+ k8sVersion, err := runner.Run()
if err != nil {
log.Logger.Warn(fmt.Sprintf("Failed to get Kubernetes version: %s", err.Error()))
- k8sVersion = []byte("Server Version: Unknown\n")
+ k8sVersion = "Server Version: Unknown\n"
}
botkubeVersion := os.Getenv("BOTKUBE_VERSION")
diff --git a/pkg/execute/fake_executor.go b/pkg/execute/fake_executor.go
new file mode 100644
index 000000000..eb19d63f5
--- /dev/null
+++ b/pkg/execute/fake_executor.go
@@ -0,0 +1,38 @@
+// +build test
+
+package execute
+
+import (
+ "fmt"
+ "strings"
+)
+
+// K8sVersion fake version send in ping response
+const K8sVersion = "v1.15.3"
+
+// KubectlResponse map for fake Kubectl responses
+var KubectlResponse = map[string]string{
+ "-n default get pods": "NAME READY STATUS RESTARTS AGE\n" +
+ "nginx-xxxxxxx-yyyyyyy 1/1 Running 1 1d",
+ "-c " + kubectlBinary + " version --short=true | grep Server": fmt.Sprintf("Server Version: %s\n", K8sVersion),
+}
+
+// FakeRunner mocks Run
+type FakeRunner struct {
+ command string
+ args []string
+}
+
+// NewCommandRunner returns new DefaultRunner
+func NewCommandRunner(command string, args []string) CommandRunner {
+ return FakeRunner{
+ command: command,
+ args: args,
+ }
+}
+
+// Run executes bash command
+func (r FakeRunner) Run() (string, error) {
+ cmd := strings.Join(r.args, " ")
+ return KubectlResponse[cmd], nil
+}
diff --git a/pkg/filterengine/filters/image_tag_checker.go b/pkg/filterengine/filters/image_tag_checker.go
index 16ce30557..02022a377 100644
--- a/pkg/filterengine/filters/image_tag_checker.go
+++ b/pkg/filterengine/filters/image_tag_checker.go
@@ -3,6 +3,7 @@ package filters
import (
"strings"
+ "github.com/infracloudio/botkube/pkg/config"
"github.com/infracloudio/botkube/pkg/events"
"github.com/infracloudio/botkube/pkg/filterengine"
log "github.com/infracloudio/botkube/pkg/logging"
@@ -24,7 +25,7 @@ func init() {
// Run filers and modifies event struct
func (f ImageTagChecker) Run(object interface{}, event *events.Event) {
- if event.Kind != "Pod" && event.Type != "create" {
+ if event.Kind != "Pod" || event.Type != config.CreateEvent {
return
}
podObj, ok := object.(*apiV1.Pod)
diff --git a/pkg/filterengine/filters/ingress_validator.go b/pkg/filterengine/filters/ingress_validator.go
index 11817aa7c..d79444cf2 100644
--- a/pkg/filterengine/filters/ingress_validator.go
+++ b/pkg/filterengine/filters/ingress_validator.go
@@ -1,6 +1,9 @@
package filters
import (
+ "fmt"
+
+ "github.com/infracloudio/botkube/pkg/config"
"github.com/infracloudio/botkube/pkg/events"
"github.com/infracloudio/botkube/pkg/filterengine"
log "github.com/infracloudio/botkube/pkg/logging"
@@ -22,7 +25,7 @@ func init() {
// Run filers and modifies event struct
func (iv IngressValidator) Run(object interface{}, event *events.Event) {
- if event.Kind != "Ingress" && event.Type != "create" {
+ if event.Kind != "Ingress" || event.Type != config.CreateEvent {
return
}
ingressObj, ok := object.(*extV1beta1.Ingress)
@@ -43,11 +46,9 @@ func (iv IngressValidator) Run(object interface{}, event *events.Event) {
}
_, err := ValidServicePort(serviceName, ns, int32(servicePort))
if err != nil {
- event.Messages = append(event.Messages, "Service "+serviceName+" used in ingress config does not exist or port not exposed\n")
- event.Level = events.Warn
+ event.Warnings = append(event.Warnings, fmt.Sprintf("Service '%s' used in ingress '%s' config does not exist or port '%v' not exposed\n", serviceName, ingressObj.Name, servicePort))
}
}
-
}
// Check if tls secret exists
diff --git a/pkg/notify/mattermost.go b/pkg/notify/mattermost.go
index 089d05e89..b1f468d1d 100644
--- a/pkg/notify/mattermost.go
+++ b/pkg/notify/mattermost.go
@@ -115,6 +115,17 @@ func (m *Mattermost) SendEvent(event events.Event) error {
})
}
+ if len(event.Warnings) > 0 {
+ rec := ""
+ for _, r := range event.Warnings {
+ rec = rec + r
+ }
+ fields = append(fields, &model.SlackAttachmentField{
+ Title: "Warnings",
+ Value: rec,
+ })
+ }
+
// Add clustername in the message
fields = append(fields, &model.SlackAttachmentField{
Title: "Cluster",
diff --git a/pkg/notify/slack.go b/pkg/notify/slack.go
index 79c567aea..2f9618e16 100644
--- a/pkg/notify/slack.go
+++ b/pkg/notify/slack.go
@@ -11,7 +11,13 @@ import (
"github.com/nlopes/slack"
)
-var attachmentColor map[events.Level]string
+var attachmentColor = map[events.Level]string{
+ events.Info: "good",
+ events.Warn: "warning",
+ events.Debug: "good",
+ events.Error: "danger",
+ events.Critical: "danger",
+}
// Slack contains Token for authentication with slack and Channel name to send notification to
type Slack struct {
@@ -19,18 +25,11 @@ type Slack struct {
Channel string
ClusterName string
NotifType config.NotifType
+ SlackURL string // Useful only for testing
}
// NewSlack returns new Slack object
func NewSlack(c *config.Config) Notifier {
- attachmentColor = map[events.Level]string{
- events.Info: "good",
- events.Warn: "warning",
- events.Debug: "good",
- events.Error: "danger",
- events.Critical: "danger",
- }
-
return &Slack{
Token: c.Communications.Slack.Token,
Channel: c.Communications.Slack.Channel,
@@ -39,18 +38,9 @@ func NewSlack(c *config.Config) Notifier {
}
}
-// SendEvent sends event notification to slack
-func (s *Slack) SendEvent(event events.Event) error {
- log.Logger.Debug(fmt.Sprintf(">> Sending to slack: %+v", event))
-
- api := slack.New(s.Token)
- params := slack.PostMessageParameters{
- AsUser: true,
- }
-
- var attachment slack.Attachment
-
- switch s.NotifType {
+// FormatSlackMessage with attachments
+func FormatSlackMessage(event events.Event, notifyType config.NotifType, clusterName string) (attachment slack.Attachment) {
+ switch notifyType {
case config.LongNotify:
attachment = slack.Attachment{
Fields: []slack.AttachmentField{
@@ -113,10 +103,21 @@ func (s *Slack) SendEvent(event events.Event) error {
})
}
+ if len(event.Warnings) > 0 {
+ rec := ""
+ for _, r := range event.Warnings {
+ rec = rec + r
+ }
+ attachment.Fields = append(attachment.Fields, slack.AttachmentField{
+ Title: "Warnings",
+ Value: rec,
+ })
+ }
+
// Add clustername in the message
attachment.Fields = append(attachment.Fields, slack.AttachmentField{
Title: "Cluster",
- Value: s.ClusterName,
+ Value: clusterName,
})
case config.ShortNotify:
@@ -124,7 +125,7 @@ func (s *Slack) SendEvent(event events.Event) error {
default:
// set missing cluster name to event object
- event.Cluster = s.ClusterName
+ event.Cluster = clusterName
attachment = slack.Attachment{
Fields: []slack.AttachmentField{
{
@@ -141,13 +142,23 @@ func (s *Slack) SendEvent(event events.Event) error {
if ts > "0" {
attachment.Ts = ts
}
-
attachment.Color = attachmentColor[event.Level]
- params.Attachments = []slack.Attachment{attachment}
+ return attachment
+}
+
+// SendEvent sends event notification to slack
+func (s *Slack) SendEvent(event events.Event) error {
+ log.Logger.Debug(fmt.Sprintf(">> Sending to slack: %+v", event))
+
+ api := slack.New(s.Token)
+ if len(s.SlackURL) != 0 {
+ api = slack.New(s.Token, slack.OptionAPIURL(s.SlackURL))
+ }
+ attachment := FormatSlackMessage(event, s.NotifType, s.ClusterName)
// non empty value in event.channel demands redirection of events to a different channel
if event.Channel != "" {
- channelID, timestamp, err := api.PostMessage(event.Channel, "", params)
+ channelID, timestamp, err := api.PostMessage(event.Channel, slack.MsgOptionAttachments(attachment), slack.MsgOptionAsUser(true))
if err != nil {
log.Logger.Errorf("Error in sending slack message %s", err.Error())
// send error message to default channel
@@ -164,7 +175,7 @@ func (s *Slack) SendEvent(event events.Event) error {
log.Logger.Debugf("Event successfully sent to channel %s at %s", channelID, timestamp)
} else {
// empty value in event.channel sends notifications to default channel.
- channelID, timestamp, err := api.PostMessage(s.Channel, "", params)
+ channelID, timestamp, err := api.PostMessage(s.Channel, slack.MsgOptionAttachments(attachment), slack.MsgOptionAsUser(true))
if err != nil {
log.Logger.Errorf("Error in sending slack message %s", err.Error())
return err
@@ -179,11 +190,11 @@ func (s *Slack) SendMessage(msg string) error {
log.Logger.Debug(fmt.Sprintf(">> Sending to slack: %+v", msg))
api := slack.New(s.Token)
- params := slack.PostMessageParameters{
- AsUser: true,
+ if len(s.SlackURL) != 0 {
+ api = slack.New(s.Token, slack.OptionAPIURL(s.SlackURL))
}
- channelID, timestamp, err := api.PostMessage(s.Channel, msg, params)
+ channelID, timestamp, err := api.PostMessage(s.Channel, slack.MsgOptionText(msg, false), slack.MsgOptionAsUser(true))
if err != nil {
log.Logger.Errorf("Error in sending slack message %s", err.Error())
return err
diff --git a/test/e2e/command/botkube.go b/test/e2e/command/botkube.go
new file mode 100644
index 000000000..a22e88ad9
--- /dev/null
+++ b/test/e2e/command/botkube.go
@@ -0,0 +1,156 @@
+package command
+
+import (
+ "encoding/json"
+ "fmt"
+ "os"
+ "strings"
+ "testing"
+ "time"
+
+ "github.com/infracloudio/botkube/pkg/config"
+ "github.com/infracloudio/botkube/pkg/execute"
+ "github.com/infracloudio/botkube/test/e2e/utils"
+ "github.com/nlopes/slack"
+ "github.com/stretchr/testify/assert"
+ "k8s.io/api/core/v1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+type botkubeCommand struct {
+ command string
+ expected string
+}
+
+// Send botkube command via Slack message and check if BotKube returns correct response
+func (c *context) testBotkubeCommand(t *testing.T) {
+ botkubeVersion := os.Getenv("BOTKUBE_VERSION")
+ // Test cases
+ tests := map[string]botkubeCommand{
+ "BotKube ping": {
+ command: "ping",
+ expected: fmt.Sprintf("```pong from cluster '%s'\n\nK8s Server Version: %s\nBotKube version: %s```", c.Config.Settings.ClusterName, execute.K8sVersion, botkubeVersion),
+ },
+ "BotKube filters list": {
+ command: "filters list",
+ expected: "FILTER ENABLED DESCRIPTION\n" +
+ "IngressValidator true Checks if services and tls secrets used in ingress specs are available.\n" +
+ "JobStatusChecker true Sends notifications only when job succeeds and ignores other job update events.\n" +
+ "NodeEventsChecker true Sends notifications on node level critical events.\n" +
+ "PodLabelChecker true Checks and adds recommedations if labels are missing in the pod specs.\n" +
+ "ImageTagChecker true Checks and adds recommendation if 'latest' image tag is used for container image.\n",
+ },
+ }
+
+ for name, test := range tests {
+ t.Run(name, func(t *testing.T) {
+ // Send message to a channel
+ c.SlackServer.SendMessageToBot(c.Config.Communications.Slack.Channel, test.command)
+
+ // Get last seen slack message
+ time.Sleep(time.Second)
+ lastSeenMsg := c.GetLastSeenSlackMessage()
+
+ // Convert text message into Slack message structure
+ m := slack.Message{}
+ err := json.Unmarshal([]byte(lastSeenMsg), &m)
+ assert.NoError(t, err, "message should decode properly")
+ assert.Equal(t, c.Config.Communications.Slack.Channel, m.Channel)
+ switch test.command {
+ case "filters list":
+ fl := compareFilters(strings.Split(test.expected, "\n"), strings.Split(strings.Trim(m.Text, "```"), "\n"))
+ assert.Equal(t, fl, true)
+ default:
+ assert.Equal(t, test.expected, m.Text)
+ }
+ })
+ }
+}
+
+func compareFilters(expected, actual []string) bool {
+ if len(expected) != len(actual) {
+ return false
+ }
+
+ // Compare slices
+ for _, a := range actual {
+ found := false
+ for _, e := range expected {
+ if a == e {
+ found = true
+ break
+ }
+ }
+ if !found {
+ return false
+ }
+ }
+ return true
+}
+
+// Test disable notification with BotKube notifier command
+// - disable notifier with '@BotKube notifier stop'
+// - create pod and verify BotKube doesn't send notification
+// - enable notifier with '@BotKube notifier start'
+func (c *context) testNotifierCommand(t *testing.T) {
+ // Disable notifier with @BotKube notifier stop
+ t.Run("disable notifier", func(t *testing.T) {
+ // Send message to a channel
+ c.SlackServer.SendMessageToBot(c.Config.Communications.Slack.Channel, "notifier stop")
+
+ // Get last seen slack message
+ time.Sleep(time.Second)
+ lastSeenMsg := c.GetLastSeenSlackMessage()
+
+ // Convert text message into Slack message structure
+ m := slack.Message{}
+ err := json.Unmarshal([]byte(lastSeenMsg), &m)
+ assert.NoError(t, err, "message should decode properly")
+ assert.Equal(t, c.Config.Communications.Slack.Channel, m.Channel)
+ assert.Equal(t, fmt.Sprintf("```Sure! I won't send you notifications from cluster '%s' anymore.```", c.Config.Settings.ClusterName), m.Text)
+ assert.Equal(t, config.Notify, false)
+ })
+
+ // Create pod and verify that BotKube is not sending notifications
+ pod := utils.CreateObjects{
+ Kind: "pod",
+ Namespace: "test",
+ Specs: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "test-pod-notifier"}},
+ Expected: utils.SlackMessage{
+ Attachments: []slack.Attachment{{Color: "good", Fields: []slack.AttachmentField{{Title: "Pod create", Value: "Pod `test-pod` in of cluster `test-cluster-1`, namespace `test` has been created:\n```Resource created\nRecommendations:\n- pod 'test-pod' creation without labels should be avoided.\n```", Short: false}}, Footer: "BotKube"}},
+ },
+ }
+ t.Run("create resource", func(t *testing.T) {
+ // Inject an event into the fake client.
+ utils.CreateResource(t, pod)
+
+ // Get last seen slack message
+ time.Sleep(time.Second)
+ lastSeenMsg := c.GetLastSeenSlackMessage()
+
+ // Convert text message into Slack message structure
+ m := slack.Message{}
+ err := json.Unmarshal([]byte(lastSeenMsg), &m)
+ assert.NoError(t, err, "message should decode properly")
+ assert.Equal(t, c.Config.Communications.Slack.Channel, m.Channel)
+ assert.NotEqual(t, pod.Expected.Attachments, m.Attachments)
+ })
+
+ // Revert and Enable notifier
+ t.Run("Enable notifier", func(t *testing.T) {
+ // Send message to a channel
+ c.SlackServer.SendMessageToBot(c.Config.Communications.Slack.Channel, "notifier start")
+
+ // Get last seen slack message
+ time.Sleep(time.Second)
+ lastSeenMsg := c.GetLastSeenSlackMessage()
+
+ // Convert text message into Slack message structure
+ m := slack.Message{}
+ err := json.Unmarshal([]byte(lastSeenMsg), &m)
+ assert.NoError(t, err, "message should decode properly")
+ assert.Equal(t, c.Config.Communications.Slack.Channel, m.Channel)
+ assert.Equal(t, fmt.Sprintf("```Brace yourselves, notifications are coming from cluster '%s'.```", c.Config.Settings.ClusterName), m.Text)
+ assert.Equal(t, config.Notify, true)
+ })
+}
diff --git a/test/e2e/command/kubectl.go b/test/e2e/command/kubectl.go
new file mode 100644
index 000000000..b0f9fed4b
--- /dev/null
+++ b/test/e2e/command/kubectl.go
@@ -0,0 +1,66 @@
+package command
+
+import (
+ "encoding/json"
+ "fmt"
+ "testing"
+ "time"
+
+ "github.com/infracloudio/botkube/pkg/execute"
+ "github.com/infracloudio/botkube/test/e2e/env"
+ "github.com/nlopes/slack"
+ "github.com/stretchr/testify/assert"
+)
+
+type kubectlCommand struct {
+ command string
+ expected string
+}
+
+type context struct {
+ *env.TestEnv
+}
+
+// Send kubectl command via Slack message and check if BotKube returns correct response
+func (c *context) testKubectlCommand(t *testing.T) {
+ // Test cases
+ tests := map[string]kubectlCommand{
+ "BotKube get pods": {
+ command: "get pods",
+ expected: fmt.Sprintf("```Cluster: %s\n%s```", c.Config.Settings.ClusterName, execute.KubectlResponse["-n default get pods"]),
+ },
+ }
+
+ for name, test := range tests {
+ t.Run(name, func(t *testing.T) {
+ // Send message to a channel
+ c.SlackServer.SendMessageToBot(c.Config.Communications.Slack.Channel, test.command)
+
+ // Get last seen slack message
+ time.Sleep(time.Second)
+ lastSeenMsg := c.GetLastSeenSlackMessage()
+
+ // Convert text message into Slack message structure
+ m := slack.Message{}
+ err := json.Unmarshal([]byte(lastSeenMsg), &m)
+ assert.NoError(t, err, "message should decode properly")
+ assert.Equal(t, c.Config.Communications.Slack.Channel, m.Channel)
+ assert.Equal(t, test.expected, m.Text)
+ })
+ }
+}
+
+// Run tests
+func (c *context) Run(t *testing.T) {
+ // Run kubectl tests
+ t.Run("Test Kubectl command", c.testKubectlCommand)
+ t.Run("Test BotKube command", c.testBotkubeCommand)
+ t.Run("Test disable notifier", c.testNotifierCommand)
+}
+
+// E2ETests runs command execution tests
+func E2ETests(testEnv *env.TestEnv) env.E2ETest {
+ return &context{
+ testEnv,
+ }
+}
diff --git a/test/e2e/e2e_test.go b/test/e2e/e2e_test.go
new file mode 100644
index 000000000..69339c487
--- /dev/null
+++ b/test/e2e/e2e_test.go
@@ -0,0 +1,74 @@
+package e2e
+
+import (
+ "log"
+ "testing"
+ "time"
+
+ "github.com/infracloudio/botkube/pkg/bot"
+ "github.com/infracloudio/botkube/pkg/controller"
+ "github.com/infracloudio/botkube/pkg/notify"
+ "github.com/infracloudio/botkube/pkg/utils"
+ "github.com/infracloudio/botkube/test/e2e/command"
+ "github.com/infracloudio/botkube/test/e2e/env"
+ "github.com/infracloudio/botkube/test/e2e/filters"
+ "github.com/infracloudio/botkube/test/e2e/notifier/create"
+ "github.com/infracloudio/botkube/test/e2e/welcome"
+)
+
+// TestRun run e2e integration tests
+func TestRun(t *testing.T) {
+ // New Environment to run integration tests
+ testEnv := env.New()
+
+ // Fake notifiers
+ fakeSlackNotifier := ¬ify.Slack{
+ Token: testEnv.Config.Communications.Slack.Token,
+ Channel: testEnv.Config.Communications.Slack.Channel,
+ ClusterName: testEnv.Config.Settings.ClusterName,
+ NotifType: testEnv.Config.Communications.Slack.NotifType,
+ SlackURL: testEnv.SlackServer.GetAPIURL(),
+ }
+ notifiers := []notify.Notifier{fakeSlackNotifier}
+
+ utils.KubeClient = testEnv.K8sClient
+ utils.InitInformerMap()
+
+ // Start controller with fake notifiers
+ go controller.RegisterInformers(testEnv.Config, notifiers)
+ t.Run("Welcome", welcome.E2ETests(testEnv))
+
+ // Start fake Slack bot
+ StartFakeSlackBot(testEnv)
+ time.Sleep(time.Second)
+
+ // Make test suite
+ suite := map[string]env.E2ETest{
+ "notifier": create.E2ETests(testEnv),
+ "command": command.E2ETests(testEnv),
+ "filters": filters.E2ETests(testEnv),
+ }
+
+ // Run test suite
+ for name, test := range suite {
+ t.Run(name, test.Run)
+ }
+}
+
+// StartFakeSlackBot makes connection to mocked slack apiserver
+func StartFakeSlackBot(testenv *env.TestEnv) {
+ if testenv.Config.Communications.Slack.Enabled {
+ log.Println("Starting fake Slack bot")
+
+ // Fake bot
+ sb := &bot.SlackBot{
+ Token: testenv.Config.Communications.Slack.Token,
+ AllowKubectl: testenv.Config.Settings.AllowKubectl,
+ ClusterName: testenv.Config.Settings.ClusterName,
+ ChannelName: testenv.Config.Communications.Slack.Channel,
+ SlackURL: testenv.SlackServer.GetAPIURL(),
+ BotID: testenv.SlackServer.BotID,
+ }
+ go sb.Start()
+ }
+}
diff --git a/test/e2e/env/env.go b/test/e2e/env/env.go
new file mode 100644
index 000000000..4142cb8fb
--- /dev/null
+++ b/test/e2e/env/env.go
@@ -0,0 +1,78 @@
+package env
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "testing"
+
+ "github.com/infracloudio/botkube/pkg/config"
+ "github.com/nlopes/slack"
+ "github.com/nlopes/slack/slacktest"
+ "k8s.io/client-go/kubernetes"
+ "k8s.io/client-go/kubernetes/fake"
+)
+
+// TestEnv to store objects required for e2e testing
+// K8sClient : Fake K8s client to mock resource creation
+// SlackServer : Fake Slack server
+// SlackMessages: Channel to store incoming Slack messages from BotKube
+// Config : BotKube config provided with config.yaml
+type TestEnv struct {
+ K8sClient kubernetes.Interface
+ SlackServer *slacktest.Server
+ SlackMessages chan (*slack.MessageEvent)
+ Config *config.Config
+}
+
+// E2ETest interface to run tests
+type E2ETest interface {
+ Run(*testing.T)
+}
+
+// New creates TestEnv and populate required objects
+func New() *TestEnv {
+ testEnv := &TestEnv{}
+
+ conf, err := config.New()
+ if err != nil {
+ log.Fatal(fmt.Sprintf("Error in loading configuration. Error:%s", err.Error()))
+ }
+ testEnv.Config = conf
+
+ // Set Slack Api token
+ testEnv.Config.Communications.Slack.Enabled = true
+ testEnv.Config.Communications.Slack.Token = "ABCDEFG"
+ testEnv.Config.Communications.Slack.Channel = "cloud-alerts"
+
+ // Add settings
+ testEnv.Config.Settings.ClusterName = "test-cluster-1"
+ testEnv.Config.Settings.AllowKubectl = true
+
+ // Set fake BotKube version
+ os.Setenv("BOTKUBE_VERSION", "v9.99.9")
+
+ testEnv.K8sClient = fake.NewSimpleClientset()
+ testEnv.SlackMessages = make(chan (*slack.MessageEvent), 1)
+ testEnv.SetupFakeSlack()
+
+ return testEnv
+}
+
+// SetupFakeSlack create fake Slack server to mock Slack
+func (e *TestEnv) SetupFakeSlack() {
+ s := slacktest.NewTestServer()
+ s.SetBotName("BotKube")
+ go s.Start()
+
+ e.SlackServer = s
+}
+
+// GetLastSeenSlackMessage return last message received by fake slack server
+func (e TestEnv) GetLastSeenSlackMessage() string {
+ allSeenMessages := e.SlackServer.GetSeenOutboundMessages()
+ if len(allSeenMessages) != 0 {
+ return allSeenMessages[len(allSeenMessages)-1]
+ }
+ return ""
+}
diff --git a/test/e2e/filters/filters.go b/test/e2e/filters/filters.go
new file mode 100644
index 000000000..cb7a3a20c
--- /dev/null
+++ b/test/e2e/filters/filters.go
@@ -0,0 +1,83 @@
+package filters
+
+import (
+ "encoding/json"
+ "testing"
+ "time"
+
+ "github.com/infracloudio/botkube/test/e2e/env"
+ "github.com/infracloudio/botkube/test/e2e/utils"
+ "github.com/nlopes/slack"
+ "github.com/stretchr/testify/assert"
+ "k8s.io/api/core/v1"
+ extV1beta1 "k8s.io/api/extensions/v1beta1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/util/intstr"
+)
+
+type context struct {
+ *env.TestEnv
+}
+
+// Test if BotKube sends notification when a resource is created
+func (c *context) testFilters(t *testing.T) {
+ // Test cases
+ tests := map[string]utils.CreateObjects{
+ "test ImageTagChecker filter": {
+ Kind: "pod",
+ Namespace: "test",
+ Specs: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "nginx-pod", Labels: map[string]string{"env": "test"}}, Spec: v1.PodSpec{Containers: []v1.Container{{Name: "nginx", Image: "nginx:latest"}}}},
+ Expected: utils.SlackMessage{
+ Attachments: []slack.Attachment{{Color: "good", Fields: []slack.AttachmentField{{Title: "Pod create", Value: "Pod `nginx-pod` in of cluster `test-cluster-1`, namespace `test` has been created:\n```Resource created\nRecommendations:\n- :latest tag used in image 'nginx:latest' of Container 'nginx' should be avoided.\n```", Short: false}}, Footer: "BotKube"}},
+ },
+ },
+
+ "test PodLabelChecker filter": {
+ Kind: "pod",
+ Namespace: "test",
+ Specs: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "pod-wo-label"}},
+ Expected: utils.SlackMessage{
+ Attachments: []slack.Attachment{{Color: "good", Fields: []slack.AttachmentField{{Title: "Pod create", Value: "Pod `pod-wo-label` in of cluster `test-cluster-1`, namespace `test` has been created:\n```Resource created\nRecommendations:\n- pod 'pod-wo-label' creation without labels should be avoided.\n```", Short: false}}, Footer: "BotKube"}},
+ },
+ },
+
+ "test IngressValidator filter": {
+ Kind: "ingress",
+ Namespace: "test",
+ Specs: &extV1beta1.Ingress{ObjectMeta: metav1.ObjectMeta{Name: "ingress-with-service"}, Spec: extV1beta1.IngressSpec{Rules: []extV1beta1.IngressRule{{IngressRuleValue: extV1beta1.IngressRuleValue{HTTP: &extV1beta1.HTTPIngressRuleValue{Paths: []extV1beta1.HTTPIngressPath{{Path: "testpath", Backend: extV1beta1.IngressBackend{ServiceName: "test-service", ServicePort: intstr.FromInt(80)}}}}}}}}},
+ Expected: utils.SlackMessage{
+ Attachments: []slack.Attachment{{Color: "good", Fields: []slack.AttachmentField{{Title: "Ingress create", Value: "Ingress `ingress-with-service` in of cluster `test-cluster-1`, namespace `test` has been created:\n```Resource created\nWarnings:\n- Service 'test-service' used in ingress 'ingress-with-service' config does not exist or port '80' not exposed\n```", Short: false}}, Footer: "BotKube"}},
+ },
+ },
+ }
+
+ for name, test := range tests {
+ t.Run(name, func(t *testing.T) {
+ // Inject an event into the fake client.
+ utils.CreateResource(t, test)
+
+ // Get last seen slack message
+ time.Sleep(time.Second)
+ lastSeenMsg := c.GetLastSeenSlackMessage()
+
+ // Convert text message into Slack message structure
+ m := slack.Message{}
+ err := json.Unmarshal([]byte(lastSeenMsg), &m)
+ assert.NoError(t, err, "message should decode properly")
+ assert.Equal(t, c.Config.Communications.Slack.Channel, m.Channel)
+ assert.Equal(t, test.Expected.Attachments, m.Attachments)
+ })
+ }
+}
+
+// Run tests
+func (c *context) Run(t *testing.T) {
+ t.Run("test filters", c.testFilters)
+}
+
+// E2ETests runs filter tests
+func E2ETests(testEnv *env.TestEnv) env.E2ETest {
+ return &context{
+ testEnv,
+ }
+}
diff --git a/test/e2e/notifier/create/create.go b/test/e2e/notifier/create/create.go
new file mode 100644
index 000000000..a7826f2a9
--- /dev/null
+++ b/test/e2e/notifier/create/create.go
@@ -0,0 +1,77 @@
+package create
+
+import (
+ "encoding/json"
+ "testing"
+ "time"
+
+ "github.com/infracloudio/botkube/pkg/config"
+ "github.com/infracloudio/botkube/pkg/utils"
+ "github.com/infracloudio/botkube/test/e2e/env"
+ testutils "github.com/infracloudio/botkube/test/e2e/utils"
+ "github.com/nlopes/slack"
+ "github.com/stretchr/testify/assert"
+ "k8s.io/api/core/v1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+type context struct {
+ *env.TestEnv
+}
+
+// Test if BotKube sends notification when a resource is created
+func (c *context) testCreateResource(t *testing.T) {
+ // Test cases
+ tests := map[string]testutils.CreateObjects{
+ "create pod in configured namespace": {
+ Kind: "pod",
+ Namespace: "test",
+ Specs: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "test-pod"}},
+ Expected: testutils.SlackMessage{
+ Attachments: []slack.Attachment{{Color: "good", Fields: []slack.AttachmentField{{Title: "Pod create", Value: "Pod `test-pod` in of cluster `test-cluster-1`, namespace `test` has been created:\n```Resource created\nRecommendations:\n- pod 'test-pod' creation without labels should be avoided.\n```", Short: false}}, Footer: "BotKube"}},
+ },
+ },
+ "create service in configured namespace": {
+ Kind: "service",
+ Namespace: "test",
+ Specs: &v1.Service{ObjectMeta: metav1.ObjectMeta{Name: "test-service"}},
+ Expected: testutils.SlackMessage{
+ Attachments: []slack.Attachment{{Color: "good", Fields: []slack.AttachmentField{{Title: "Service create", Value: "Service `test-service` in of cluster `test-cluster-1`, namespace `test` has been created:\n```Resource created\n```", Short: false}}, Footer: "BotKube"}},
+ },
+ },
+ }
+
+ for name, test := range tests {
+ t.Run(name, func(t *testing.T) {
+ // Inject an event into the fake client.
+ testutils.CreateResource(t, test)
+
+ // Get last seen slack message
+ time.Sleep(time.Second)
+ lastSeenMsg := c.GetLastSeenSlackMessage()
+
+ // Convert text message into Slack message structure
+ m := slack.Message{}
+ err := json.Unmarshal([]byte(lastSeenMsg), &m)
+ assert.NoError(t, err, "message should decode properly")
+ assert.Equal(t, c.Config.Communications.Slack.Channel, m.Channel)
+ assert.Equal(t, c.Config.Communications.Slack.Channel, m.Channel)
+ assert.Equal(t, test.Expected.Attachments, m.Attachments)
+ isAllowed := utils.AllowedEventKindsMap[utils.EventKind{Resource: test.Kind, Namespace: "all", EventType: config.CreateEvent}] ||
+ utils.AllowedEventKindsMap[utils.EventKind{Resource: test.Kind, Namespace: test.Namespace, EventType: config.CreateEvent}]
+ assert.Equal(t, isAllowed, true)
+ })
+ }
+}
+
+// Run tests
+func (c *context) Run(t *testing.T) {
+ t.Run("create resource", c.testCreateResource)
+}
+
+// E2ETests runs create notification tests
+func E2ETests(testEnv *env.TestEnv) env.E2ETest {
+ return &context{
+ testEnv,
+ }
+}
diff --git a/test/e2e/utils/utils.go b/test/e2e/utils/utils.go
new file mode 100644
index 000000000..d0804d541
--- /dev/null
+++ b/test/e2e/utils/utils.go
@@ -0,0 +1,51 @@
+package utils
+
+import (
+ "testing"
+
+ "github.com/infracloudio/botkube/pkg/config"
+ "github.com/infracloudio/botkube/pkg/utils"
+ "github.com/nlopes/slack"
+ "k8s.io/api/core/v1"
+ extV1beta1 "k8s.io/api/extensions/v1beta1"
+ "k8s.io/apimachinery/pkg/runtime"
+)
+
+// SlackMessage structure
+type SlackMessage struct {
+ Text string
+ Attachments []slack.Attachment
+}
+
+// CreateObjects stores specs for creating a k8s fake object and expected Slack response
+type CreateObjects struct {
+ Kind string
+ Namespace string
+ Specs runtime.Object
+ NotifType config.NotifType
+ Expected SlackMessage
+}
+
+// CreateResource with fake client
+func CreateResource(t *testing.T, obj CreateObjects) {
+ switch obj.Kind {
+ case "pod":
+ s := obj.Specs.(*v1.Pod)
+ _, err := utils.KubeClient.CoreV1().Pods(obj.Namespace).Create(s)
+ if err != nil {
+ t.Fatalf("Failed to create pod: %v", err)
+ }
+ case "service":
+ s := obj.Specs.(*v1.Service)
+ _, err := utils.KubeClient.CoreV1().Services(obj.Namespace).Create(s)
+ if err != nil {
+ t.Fatalf("Failed to create service: %v", err)
+ }
+ case "ingress":
+ s := obj.Specs.(*extV1beta1.Ingress)
+ _, err := utils.KubeClient.ExtensionsV1beta1().Ingresses(obj.Namespace).Create(s)
+ if err != nil {
+ t.Fatalf("Failed to create service: %v", err)
+ }
+ }
+}
diff --git a/test/e2e/welcome/welcome.go b/test/e2e/welcome/welcome.go
new file mode 100644
index 000000000..b89a22904
--- /dev/null
+++ b/test/e2e/welcome/welcome.go
@@ -0,0 +1,40 @@
+package welcome
+
+import (
+ "encoding/json"
+ "testing"
+ "time"
+
+ "github.com/infracloudio/botkube/test/e2e/env"
+ "github.com/nlopes/slack"
+ "github.com/stretchr/testify/assert"
+)
+
+type context struct {
+ Env *env.TestEnv
+}
+
+// Test if BotKube sends welcome message to the configured slack channel after start
+func (c *context) testWelcome(t *testing.T) {
+ expected := "...and now my watch begins for cluster 'test-cluster-1'! :crossed_swords:"
+
+ // Get last seen slack message
+ time.Sleep(time.Second)
+ lastSeenMsg := c.Env.GetLastSeenSlackMessage()
+
+ // Convert text message into Slack message structure
+ m := slack.Message{}
+ err := json.Unmarshal([]byte(lastSeenMsg), &m)
+ assert.NoError(t, err, "message should decode properly")
+ assert.Equal(t, c.Env.Config.Communications.Slack.Channel, m.Channel)
+ assert.Equal(t, expected, m.Text)
+}
+
+// E2ETests run welcome tests
+func E2ETests(testEnv *env.TestEnv) func(*testing.T) {
+ ctx := &context{
+ Env: testEnv,
+ }
+
+ return ctx.testWelcome
+}
diff --git a/vendor/github.com/evanphx/json-patch/.travis.yml b/vendor/github.com/evanphx/json-patch/.travis.yml
new file mode 100644
index 000000000..2092c72c4
--- /dev/null
+++ b/vendor/github.com/evanphx/json-patch/.travis.yml
@@ -0,0 +1,16 @@
+language: go
+
+go:
+ - 1.8
+ - 1.7
+
+install:
+ - if ! go get code.google.com/p/go.tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi
+ - go get github.com/jessevdk/go-flags
+
+script:
+ - go get
+ - go test -cover ./...
+
+notifications:
+ email: false
diff --git a/vendor/github.com/evanphx/json-patch/LICENSE b/vendor/github.com/evanphx/json-patch/LICENSE
new file mode 100644
index 000000000..0eb9b72d8
--- /dev/null
+++ b/vendor/github.com/evanphx/json-patch/LICENSE
@@ -0,0 +1,25 @@
+Copyright (c) 2014, Evan Phoenix
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+* Neither the name of the Evan Phoenix nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/evanphx/json-patch/README.md b/vendor/github.com/evanphx/json-patch/README.md
new file mode 100644
index 000000000..9c7f87f7c
--- /dev/null
+++ b/vendor/github.com/evanphx/json-patch/README.md
@@ -0,0 +1,297 @@
+# JSON-Patch
+`jsonpatch` is a library which provides functionallity for both applying
+[RFC6902 JSON patches](http://tools.ietf.org/html/rfc6902) against documents, as
+well as for calculating & applying [RFC7396 JSON merge patches](https://tools.ietf.org/html/rfc7396).
+
+[![GoDoc](https://godoc.org/github.com/evanphx/json-patch?status.svg)](http://godoc.org/github.com/evanphx/json-patch)
+[![Build Status](https://travis-ci.org/evanphx/json-patch.svg?branch=master)](https://travis-ci.org/evanphx/json-patch)
+[![Report Card](https://goreportcard.com/badge/github.com/evanphx/json-patch)](https://goreportcard.com/report/github.com/evanphx/json-patch)
+
+# Get It!
+
+**Latest and greatest**:
+```bash
+go get -u github.com/evanphx/json-patch
+```
+
+**Stable Versions**:
+* Version 4: `go get -u gopkg.in/evanphx/json-patch.v4`
+
+(previous versions below `v3` are unavailable)
+
+# Use It!
+* [Create and apply a merge patch](#create-and-apply-a-merge-patch)
+* [Create and apply a JSON Patch](#create-and-apply-a-json-patch)
+* [Comparing JSON documents](#comparing-json-documents)
+* [Combine merge patches](#combine-merge-patches)
+
+
+# Configuration
+
+* There is a global configuration variable `jsonpatch.SupportNegativeIndices`.
+ This defaults to `true` and enables the non-standard practice of allowing
+ negative indices to mean indices starting at the end of an array. This
+ functionality can be disabled by setting `jsonpatch.SupportNegativeIndices =
+ false`.
+
+* There is a global configuration variable `jsonpatch.AccumulatedCopySizeLimit`,
+ which limits the total size increase in bytes caused by "copy" operations in a
+ patch. It defaults to 0, which means there is no limit.
+
+## Create and apply a merge patch
+Given both an original JSON document and a modified JSON document, you can create
+a [Merge Patch](https://tools.ietf.org/html/rfc7396) document.
+
+It can describe the changes needed to convert from the original to the
+modified JSON document.
+
+Once you have a merge patch, you can apply it to other JSON documents using the
+`jsonpatch.MergePatch(document, patch)` function.
+
+```go
+package main
+
+import (
+ "fmt"
+
+ jsonpatch "github.com/evanphx/json-patch"
+)
+
+func main() {
+ // Let's create a merge patch from these two documents...
+ original := []byte(`{"name": "John", "age": 24, "height": 3.21}`)
+ target := []byte(`{"name": "Jane", "age": 24}`)
+
+ patch, err := jsonpatch.CreateMergePatch(original, target)
+ if err != nil {
+ panic(err)
+ }
+
+ // Now lets apply the patch against a different JSON document...
+
+ alternative := []byte(`{"name": "Tina", "age": 28, "height": 3.75}`)
+ modifiedAlternative, err := jsonpatch.MergePatch(alternative, patch)
+
+ fmt.Printf("patch document: %s\n", patch)
+ fmt.Printf("updated alternative doc: %s\n", modifiedAlternative)
+}
+```
+
+When ran, you get the following output:
+
+```bash
+$ go run main.go
+patch document: {"height":null,"name":"Jane"}
+updated tina doc: {"age":28,"name":"Jane"}
+```
+
+## Create and apply a JSON Patch
+You can create patch objects using `DecodePatch([]byte)`, which can then
+be applied against JSON documents.
+
+The following is an example of creating a patch from two operations, and
+applying it against a JSON document.
+
+```go
+package main
+
+import (
+ "fmt"
+
+ jsonpatch "github.com/evanphx/json-patch"
+)
+
+func main() {
+ original := []byte(`{"name": "John", "age": 24, "height": 3.21}`)
+ patchJSON := []byte(`[
+ {"op": "replace", "path": "/name", "value": "Jane"},
+ {"op": "remove", "path": "/height"}
+ ]`)
+
+ patch, err := jsonpatch.DecodePatch(patchJSON)
+ if err != nil {
+ panic(err)
+ }
+
+ modified, err := patch.Apply(original)
+ if err != nil {
+ panic(err)
+ }
+
+ fmt.Printf("Original document: %s\n", original)
+ fmt.Printf("Modified document: %s\n", modified)
+}
+```
+
+When ran, you get the following output:
+
+```bash
+$ go run main.go
+Original document: {"name": "John", "age": 24, "height": 3.21}
+Modified document: {"age":24,"name":"Jane"}
+```
+
+## Comparing JSON documents
+Due to potential whitespace and ordering differences, one cannot simply compare
+JSON strings or byte-arrays directly.
+
+As such, you can instead use `jsonpatch.Equal(document1, document2)` to
+determine if two JSON documents are _structurally_ equal. This ignores
+whitespace differences, and key-value ordering.
+
+```go
+package main
+
+import (
+ "fmt"
+
+ jsonpatch "github.com/evanphx/json-patch"
+)
+
+func main() {
+ original := []byte(`{"name": "John", "age": 24, "height": 3.21}`)
+ similar := []byte(`
+ {
+ "age": 24,
+ "height": 3.21,
+ "name": "John"
+ }
+ `)
+ different := []byte(`{"name": "Jane", "age": 20, "height": 3.37}`)
+
+ if jsonpatch.Equal(original, similar) {
+ fmt.Println(`"original" is structurally equal to "similar"`)
+ }
+
+ if !jsonpatch.Equal(original, different) {
+ fmt.Println(`"original" is _not_ structurally equal to "similar"`)
+ }
+}
+```
+
+When ran, you get the following output:
+```bash
+$ go run main.go
+"original" is structurally equal to "similar"
+"original" is _not_ structurally equal to "similar"
+```
+
+## Combine merge patches
+Given two JSON merge patch documents, it is possible to combine them into a
+single merge patch which can describe both set of changes.
+
+The resulting merge patch can be used such that applying it results in a
+document structurally similar as merging each merge patch to the document
+in succession.
+
+```go
+package main
+
+import (
+ "fmt"
+
+ jsonpatch "github.com/evanphx/json-patch"
+)
+
+func main() {
+ original := []byte(`{"name": "John", "age": 24, "height": 3.21}`)
+
+ nameAndHeight := []byte(`{"height":null,"name":"Jane"}`)
+ ageAndEyes := []byte(`{"age":4.23,"eyes":"blue"}`)
+
+ // Let's combine these merge patch documents...
+ combinedPatch, err := jsonpatch.MergeMergePatches(nameAndHeight, ageAndEyes)
+ if err != nil {
+ panic(err)
+ }
+
+ // Apply each patch individual against the original document
+ withoutCombinedPatch, err := jsonpatch.MergePatch(original, nameAndHeight)
+ if err != nil {
+ panic(err)
+ }
+
+ withoutCombinedPatch, err = jsonpatch.MergePatch(withoutCombinedPatch, ageAndEyes)
+ if err != nil {
+ panic(err)
+ }
+
+ // Apply the combined patch against the original document
+
+ withCombinedPatch, err := jsonpatch.MergePatch(original, combinedPatch)
+ if err != nil {
+ panic(err)
+ }
+
+ // Do both result in the same thing? They should!
+ if jsonpatch.Equal(withCombinedPatch, withoutCombinedPatch) {
+ fmt.Println("Both JSON documents are structurally the same!")
+ }
+
+ fmt.Printf("combined merge patch: %s", combinedPatch)
+}
+```
+
+When ran, you get the following output:
+```bash
+$ go run main.go
+Both JSON documents are structurally the same!
+combined merge patch: {"age":4.23,"eyes":"blue","height":null,"name":"Jane"}
+```
+
+# CLI for comparing JSON documents
+You can install the commandline program `json-patch`.
+
+This program can take multiple JSON patch documents as arguments,
+and fed a JSON document from `stdin`. It will apply the patch(es) against
+the document and output the modified doc.
+
+**patch.1.json**
+```json
+[
+ {"op": "replace", "path": "/name", "value": "Jane"},
+ {"op": "remove", "path": "/height"}
+]
+```
+
+**patch.2.json**
+```json
+[
+ {"op": "add", "path": "/address", "value": "123 Main St"},
+ {"op": "replace", "path": "/age", "value": "21"}
+]
+```
+
+**document.json**
+```json
+{
+ "name": "John",
+ "age": 24,
+ "height": 3.21
+}
+```
+
+You can then run:
+
+```bash
+$ go install github.com/evanphx/json-patch/cmd/json-patch
+$ cat document.json | json-patch -p patch.1.json -p patch.2.json
+{"address":"123 Main St","age":"21","name":"Jane"}
+```
+
+# Help It!
+Contributions are welcomed! Leave [an issue](https://github.com/evanphx/json-patch/issues)
+or [create a PR](https://github.com/evanphx/json-patch/compare).
+
+
+Before creating a pull request, we'd ask that you make sure tests are passing
+and that you have added new tests when applicable.
+
+Contributors can run tests using:
+
+```bash
+go test -cover ./...
+```
+
+Builds for pull requests are tested automatically
+using [TravisCI](https://travis-ci.org/evanphx/json-patch).
diff --git a/vendor/github.com/evanphx/json-patch/errors.go b/vendor/github.com/evanphx/json-patch/errors.go
new file mode 100644
index 000000000..75304b443
--- /dev/null
+++ b/vendor/github.com/evanphx/json-patch/errors.go
@@ -0,0 +1,38 @@
+package jsonpatch
+
+import "fmt"
+
+// AccumulatedCopySizeError is an error type returned when the accumulated size
+// increase caused by copy operations in a patch operation has exceeded the
+// limit.
+type AccumulatedCopySizeError struct {
+ limit int64
+ accumulated int64
+}
+
+// NewAccumulatedCopySizeError returns an AccumulatedCopySizeError.
+func NewAccumulatedCopySizeError(l, a int64) *AccumulatedCopySizeError {
+ return &AccumulatedCopySizeError{limit: l, accumulated: a}
+}
+
+// Error implements the error interface.
+func (a *AccumulatedCopySizeError) Error() string {
+ return fmt.Sprintf("Unable to complete the copy, the accumulated size increase of copy is %d, exceeding the limit %d", a.accumulated, a.limit)
+}
+
+// ArraySizeError is an error type returned when the array size has exceeded
+// the limit.
+type ArraySizeError struct {
+ limit int
+ size int
+}
+
+// NewArraySizeError returns an ArraySizeError.
+func NewArraySizeError(l, s int) *ArraySizeError {
+ return &ArraySizeError{limit: l, size: s}
+}
+
+// Error implements the error interface.
+func (a *ArraySizeError) Error() string {
+ return fmt.Sprintf("Unable to create array of size %d, limit is %d", a.size, a.limit)
+}
diff --git a/vendor/github.com/evanphx/json-patch/merge.go b/vendor/github.com/evanphx/json-patch/merge.go
new file mode 100644
index 000000000..6806c4c20
--- /dev/null
+++ b/vendor/github.com/evanphx/json-patch/merge.go
@@ -0,0 +1,383 @@
+package jsonpatch
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "reflect"
+)
+
+func merge(cur, patch *lazyNode, mergeMerge bool) *lazyNode {
+ curDoc, err := cur.intoDoc()
+
+ if err != nil {
+ pruneNulls(patch)
+ return patch
+ }
+
+ patchDoc, err := patch.intoDoc()
+
+ if err != nil {
+ return patch
+ }
+
+ mergeDocs(curDoc, patchDoc, mergeMerge)
+
+ return cur
+}
+
+func mergeDocs(doc, patch *partialDoc, mergeMerge bool) {
+ for k, v := range *patch {
+ if v == nil {
+ if mergeMerge {
+ (*doc)[k] = nil
+ } else {
+ delete(*doc, k)
+ }
+ } else {
+ cur, ok := (*doc)[k]
+
+ if !ok || cur == nil {
+ pruneNulls(v)
+ (*doc)[k] = v
+ } else {
+ (*doc)[k] = merge(cur, v, mergeMerge)
+ }
+ }
+ }
+}
+
+func pruneNulls(n *lazyNode) {
+ sub, err := n.intoDoc()
+
+ if err == nil {
+ pruneDocNulls(sub)
+ } else {
+ ary, err := n.intoAry()
+
+ if err == nil {
+ pruneAryNulls(ary)
+ }
+ }
+}
+
+func pruneDocNulls(doc *partialDoc) *partialDoc {
+ for k, v := range *doc {
+ if v == nil {
+ delete(*doc, k)
+ } else {
+ pruneNulls(v)
+ }
+ }
+
+ return doc
+}
+
+func pruneAryNulls(ary *partialArray) *partialArray {
+ newAry := []*lazyNode{}
+
+ for _, v := range *ary {
+ if v != nil {
+ pruneNulls(v)
+ newAry = append(newAry, v)
+ }
+ }
+
+ *ary = newAry
+
+ return ary
+}
+
+var errBadJSONDoc = fmt.Errorf("Invalid JSON Document")
+var errBadJSONPatch = fmt.Errorf("Invalid JSON Patch")
+var errBadMergeTypes = fmt.Errorf("Mismatched JSON Documents")
+
+// MergeMergePatches merges two merge patches together, such that
+// applying this resulting merged merge patch to a document yields the same
+// as merging each merge patch to the document in succession.
+func MergeMergePatches(patch1Data, patch2Data []byte) ([]byte, error) {
+ return doMergePatch(patch1Data, patch2Data, true)
+}
+
+// MergePatch merges the patchData into the docData.
+func MergePatch(docData, patchData []byte) ([]byte, error) {
+ return doMergePatch(docData, patchData, false)
+}
+
+func doMergePatch(docData, patchData []byte, mergeMerge bool) ([]byte, error) {
+ doc := &partialDoc{}
+
+ docErr := json.Unmarshal(docData, doc)
+
+ patch := &partialDoc{}
+
+ patchErr := json.Unmarshal(patchData, patch)
+
+ if _, ok := docErr.(*json.SyntaxError); ok {
+ return nil, errBadJSONDoc
+ }
+
+ if _, ok := patchErr.(*json.SyntaxError); ok {
+ return nil, errBadJSONPatch
+ }
+
+ if docErr == nil && *doc == nil {
+ return nil, errBadJSONDoc
+ }
+
+ if patchErr == nil && *patch == nil {
+ return nil, errBadJSONPatch
+ }
+
+ if docErr != nil || patchErr != nil {
+ // Not an error, just not a doc, so we turn straight into the patch
+ if patchErr == nil {
+ if mergeMerge {
+ doc = patch
+ } else {
+ doc = pruneDocNulls(patch)
+ }
+ } else {
+ patchAry := &partialArray{}
+ patchErr = json.Unmarshal(patchData, patchAry)
+
+ if patchErr != nil {
+ return nil, errBadJSONPatch
+ }
+
+ pruneAryNulls(patchAry)
+
+ out, patchErr := json.Marshal(patchAry)
+
+ if patchErr != nil {
+ return nil, errBadJSONPatch
+ }
+
+ return out, nil
+ }
+ } else {
+ mergeDocs(doc, patch, mergeMerge)
+ }
+
+ return json.Marshal(doc)
+}
+
+// resemblesJSONArray indicates whether the byte-slice "appears" to be
+// a JSON array or not.
+// False-positives are possible, as this function does not check the internal
+// structure of the array. It only checks that the outer syntax is present and
+// correct.
+func resemblesJSONArray(input []byte) bool {
+ input = bytes.TrimSpace(input)
+
+ hasPrefix := bytes.HasPrefix(input, []byte("["))
+ hasSuffix := bytes.HasSuffix(input, []byte("]"))
+
+ return hasPrefix && hasSuffix
+}
+
+// CreateMergePatch will return a merge patch document capable of converting
+// the original document(s) to the modified document(s).
+// The parameters can be bytes of either two JSON Documents, or two arrays of
+// JSON documents.
+// The merge patch returned follows the specification defined at http://tools.ietf.org/html/draft-ietf-appsawg-json-merge-patch-07
+func CreateMergePatch(originalJSON, modifiedJSON []byte) ([]byte, error) {
+ originalResemblesArray := resemblesJSONArray(originalJSON)
+ modifiedResemblesArray := resemblesJSONArray(modifiedJSON)
+
+ // Do both byte-slices seem like JSON arrays?
+ if originalResemblesArray && modifiedResemblesArray {
+ return createArrayMergePatch(originalJSON, modifiedJSON)
+ }
+
+ // Are both byte-slices are not arrays? Then they are likely JSON objects...
+ if !originalResemblesArray && !modifiedResemblesArray {
+ return createObjectMergePatch(originalJSON, modifiedJSON)
+ }
+
+ // None of the above? Then return an error because of mismatched types.
+ return nil, errBadMergeTypes
+}
+
+// createObjectMergePatch will return a merge-patch document capable of
+// converting the original document to the modified document.
+func createObjectMergePatch(originalJSON, modifiedJSON []byte) ([]byte, error) {
+ originalDoc := map[string]interface{}{}
+ modifiedDoc := map[string]interface{}{}
+
+ err := json.Unmarshal(originalJSON, &originalDoc)
+ if err != nil {
+ return nil, errBadJSONDoc
+ }
+
+ err = json.Unmarshal(modifiedJSON, &modifiedDoc)
+ if err != nil {
+ return nil, errBadJSONDoc
+ }
+
+ dest, err := getDiff(originalDoc, modifiedDoc)
+ if err != nil {
+ return nil, err
+ }
+
+ return json.Marshal(dest)
+}
+
+// createArrayMergePatch will return an array of merge-patch documents capable
+// of converting the original document to the modified document for each
+// pair of JSON documents provided in the arrays.
+// Arrays of mismatched sizes will result in an error.
+func createArrayMergePatch(originalJSON, modifiedJSON []byte) ([]byte, error) {
+ originalDocs := []json.RawMessage{}
+ modifiedDocs := []json.RawMessage{}
+
+ err := json.Unmarshal(originalJSON, &originalDocs)
+ if err != nil {
+ return nil, errBadJSONDoc
+ }
+
+ err = json.Unmarshal(modifiedJSON, &modifiedDocs)
+ if err != nil {
+ return nil, errBadJSONDoc
+ }
+
+ total := len(originalDocs)
+ if len(modifiedDocs) != total {
+ return nil, errBadJSONDoc
+ }
+
+ result := []json.RawMessage{}
+ for i := 0; i < len(originalDocs); i++ {
+ original := originalDocs[i]
+ modified := modifiedDocs[i]
+
+ patch, err := createObjectMergePatch(original, modified)
+ if err != nil {
+ return nil, err
+ }
+
+ result = append(result, json.RawMessage(patch))
+ }
+
+ return json.Marshal(result)
+}
+
+// Returns true if the array matches (must be json types).
+// As is idiomatic for go, an empty array is not the same as a nil array.
+func matchesArray(a, b []interface{}) bool {
+ if len(a) != len(b) {
+ return false
+ }
+ if (a == nil && b != nil) || (a != nil && b == nil) {
+ return false
+ }
+ for i := range a {
+ if !matchesValue(a[i], b[i]) {
+ return false
+ }
+ }
+ return true
+}
+
+// Returns true if the values matches (must be json types)
+// The types of the values must match, otherwise it will always return false
+// If two map[string]interface{} are given, all elements must match.
+func matchesValue(av, bv interface{}) bool {
+ if reflect.TypeOf(av) != reflect.TypeOf(bv) {
+ return false
+ }
+ switch at := av.(type) {
+ case string:
+ bt := bv.(string)
+ if bt == at {
+ return true
+ }
+ case float64:
+ bt := bv.(float64)
+ if bt == at {
+ return true
+ }
+ case bool:
+ bt := bv.(bool)
+ if bt == at {
+ return true
+ }
+ case nil:
+ // Both nil, fine.
+ return true
+ case map[string]interface{}:
+ bt := bv.(map[string]interface{})
+ for key := range at {
+ if !matchesValue(at[key], bt[key]) {
+ return false
+ }
+ }
+ for key := range bt {
+ if !matchesValue(at[key], bt[key]) {
+ return false
+ }
+ }
+ return true
+ case []interface{}:
+ bt := bv.([]interface{})
+ return matchesArray(at, bt)
+ }
+ return false
+}
+
+// getDiff returns the (recursive) difference between a and b as a map[string]interface{}.
+func getDiff(a, b map[string]interface{}) (map[string]interface{}, error) {
+ into := map[string]interface{}{}
+ for key, bv := range b {
+ av, ok := a[key]
+ // value was added
+ if !ok {
+ into[key] = bv
+ continue
+ }
+ // If types have changed, replace completely
+ if reflect.TypeOf(av) != reflect.TypeOf(bv) {
+ into[key] = bv
+ continue
+ }
+ // Types are the same, compare values
+ switch at := av.(type) {
+ case map[string]interface{}:
+ bt := bv.(map[string]interface{})
+ dst := make(map[string]interface{}, len(bt))
+ dst, err := getDiff(at, bt)
+ if err != nil {
+ return nil, err
+ }
+ if len(dst) > 0 {
+ into[key] = dst
+ }
+ case string, float64, bool:
+ if !matchesValue(av, bv) {
+ into[key] = bv
+ }
+ case []interface{}:
+ bt := bv.([]interface{})
+ if !matchesArray(at, bt) {
+ into[key] = bv
+ }
+ case nil:
+ switch bv.(type) {
+ case nil:
+ // Both nil, fine.
+ default:
+ into[key] = bv
+ }
+ default:
+ panic(fmt.Sprintf("Unknown type:%T in key %s", av, key))
+ }
+ }
+ // Now add all deleted values as nil
+ for key := range a {
+ _, found := b[key]
+ if !found {
+ into[key] = nil
+ }
+ }
+ return into, nil
+}
diff --git a/vendor/github.com/evanphx/json-patch/patch.go b/vendor/github.com/evanphx/json-patch/patch.go
new file mode 100644
index 000000000..c9cf59021
--- /dev/null
+++ b/vendor/github.com/evanphx/json-patch/patch.go
@@ -0,0 +1,696 @@
+package jsonpatch
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "strconv"
+ "strings"
+)
+
+const (
+ eRaw = iota
+ eDoc
+ eAry
+)
+
+var (
+ // SupportNegativeIndices decides whether to support non-standard practice of
+ // allowing negative indices to mean indices starting at the end of an array.
+ // Default to true.
+ SupportNegativeIndices bool = true
+ // AccumulatedCopySizeLimit limits the total size increase in bytes caused by
+ // "copy" operations in a patch.
+ AccumulatedCopySizeLimit int64 = 0
+)
+
+type lazyNode struct {
+ raw *json.RawMessage
+ doc partialDoc
+ ary partialArray
+ which int
+}
+
+type operation map[string]*json.RawMessage
+
+// Patch is an ordered collection of operations.
+type Patch []operation
+
+type partialDoc map[string]*lazyNode
+type partialArray []*lazyNode
+
+type container interface {
+ get(key string) (*lazyNode, error)
+ set(key string, val *lazyNode) error
+ add(key string, val *lazyNode) error
+ remove(key string) error
+}
+
+func newLazyNode(raw *json.RawMessage) *lazyNode {
+ return &lazyNode{raw: raw, doc: nil, ary: nil, which: eRaw}
+}
+
+func (n *lazyNode) MarshalJSON() ([]byte, error) {
+ switch n.which {
+ case eRaw:
+ return json.Marshal(n.raw)
+ case eDoc:
+ return json.Marshal(n.doc)
+ case eAry:
+ return json.Marshal(n.ary)
+ default:
+ return nil, fmt.Errorf("Unknown type")
+ }
+}
+
+func (n *lazyNode) UnmarshalJSON(data []byte) error {
+ dest := make(json.RawMessage, len(data))
+ copy(dest, data)
+ n.raw = &dest
+ n.which = eRaw
+ return nil
+}
+
+func deepCopy(src *lazyNode) (*lazyNode, int, error) {
+ if src == nil {
+ return nil, 0, nil
+ }
+ a, err := src.MarshalJSON()
+ if err != nil {
+ return nil, 0, err
+ }
+ sz := len(a)
+ ra := make(json.RawMessage, sz)
+ copy(ra, a)
+ return newLazyNode(&ra), sz, nil
+}
+
+func (n *lazyNode) intoDoc() (*partialDoc, error) {
+ if n.which == eDoc {
+ return &n.doc, nil
+ }
+
+ if n.raw == nil {
+ return nil, fmt.Errorf("Unable to unmarshal nil pointer as partial document")
+ }
+
+ err := json.Unmarshal(*n.raw, &n.doc)
+
+ if err != nil {
+ return nil, err
+ }
+
+ n.which = eDoc
+ return &n.doc, nil
+}
+
+func (n *lazyNode) intoAry() (*partialArray, error) {
+ if n.which == eAry {
+ return &n.ary, nil
+ }
+
+ if n.raw == nil {
+ return nil, fmt.Errorf("Unable to unmarshal nil pointer as partial array")
+ }
+
+ err := json.Unmarshal(*n.raw, &n.ary)
+
+ if err != nil {
+ return nil, err
+ }
+
+ n.which = eAry
+ return &n.ary, nil
+}
+
+func (n *lazyNode) compact() []byte {
+ buf := &bytes.Buffer{}
+
+ if n.raw == nil {
+ return nil
+ }
+
+ err := json.Compact(buf, *n.raw)
+
+ if err != nil {
+ return *n.raw
+ }
+
+ return buf.Bytes()
+}
+
+func (n *lazyNode) tryDoc() bool {
+ if n.raw == nil {
+ return false
+ }
+
+ err := json.Unmarshal(*n.raw, &n.doc)
+
+ if err != nil {
+ return false
+ }
+
+ n.which = eDoc
+ return true
+}
+
+func (n *lazyNode) tryAry() bool {
+ if n.raw == nil {
+ return false
+ }
+
+ err := json.Unmarshal(*n.raw, &n.ary)
+
+ if err != nil {
+ return false
+ }
+
+ n.which = eAry
+ return true
+}
+
+func (n *lazyNode) equal(o *lazyNode) bool {
+ if n.which == eRaw {
+ if !n.tryDoc() && !n.tryAry() {
+ if o.which != eRaw {
+ return false
+ }
+
+ return bytes.Equal(n.compact(), o.compact())
+ }
+ }
+
+ if n.which == eDoc {
+ if o.which == eRaw {
+ if !o.tryDoc() {
+ return false
+ }
+ }
+
+ if o.which != eDoc {
+ return false
+ }
+
+ for k, v := range n.doc {
+ ov, ok := o.doc[k]
+
+ if !ok {
+ return false
+ }
+
+ if v == nil && ov == nil {
+ continue
+ }
+
+ if !v.equal(ov) {
+ return false
+ }
+ }
+
+ return true
+ }
+
+ if o.which != eAry && !o.tryAry() {
+ return false
+ }
+
+ if len(n.ary) != len(o.ary) {
+ return false
+ }
+
+ for idx, val := range n.ary {
+ if !val.equal(o.ary[idx]) {
+ return false
+ }
+ }
+
+ return true
+}
+
+func (o operation) kind() string {
+ if obj, ok := o["op"]; ok && obj != nil {
+ var op string
+
+ err := json.Unmarshal(*obj, &op)
+
+ if err != nil {
+ return "unknown"
+ }
+
+ return op
+ }
+
+ return "unknown"
+}
+
+func (o operation) path() string {
+ if obj, ok := o["path"]; ok && obj != nil {
+ var op string
+
+ err := json.Unmarshal(*obj, &op)
+
+ if err != nil {
+ return "unknown"
+ }
+
+ return op
+ }
+
+ return "unknown"
+}
+
+func (o operation) from() string {
+ if obj, ok := o["from"]; ok && obj != nil {
+ var op string
+
+ err := json.Unmarshal(*obj, &op)
+
+ if err != nil {
+ return "unknown"
+ }
+
+ return op
+ }
+
+ return "unknown"
+}
+
+func (o operation) value() *lazyNode {
+ if obj, ok := o["value"]; ok {
+ return newLazyNode(obj)
+ }
+
+ return nil
+}
+
+func isArray(buf []byte) bool {
+Loop:
+ for _, c := range buf {
+ switch c {
+ case ' ':
+ case '\n':
+ case '\t':
+ continue
+ case '[':
+ return true
+ default:
+ break Loop
+ }
+ }
+
+ return false
+}
+
+func findObject(pd *container, path string) (container, string) {
+ doc := *pd
+
+ split := strings.Split(path, "/")
+
+ if len(split) < 2 {
+ return nil, ""
+ }
+
+ parts := split[1 : len(split)-1]
+
+ key := split[len(split)-1]
+
+ var err error
+
+ for _, part := range parts {
+
+ next, ok := doc.get(decodePatchKey(part))
+
+ if next == nil || ok != nil {
+ return nil, ""
+ }
+
+ if isArray(*next.raw) {
+ doc, err = next.intoAry()
+
+ if err != nil {
+ return nil, ""
+ }
+ } else {
+ doc, err = next.intoDoc()
+
+ if err != nil {
+ return nil, ""
+ }
+ }
+ }
+
+ return doc, decodePatchKey(key)
+}
+
+func (d *partialDoc) set(key string, val *lazyNode) error {
+ (*d)[key] = val
+ return nil
+}
+
+func (d *partialDoc) add(key string, val *lazyNode) error {
+ (*d)[key] = val
+ return nil
+}
+
+func (d *partialDoc) get(key string) (*lazyNode, error) {
+ return (*d)[key], nil
+}
+
+func (d *partialDoc) remove(key string) error {
+ _, ok := (*d)[key]
+ if !ok {
+ return fmt.Errorf("Unable to remove nonexistent key: %s", key)
+ }
+
+ delete(*d, key)
+ return nil
+}
+
+// set should only be used to implement the "replace" operation, so "key" must
+// be an already existing index in "d".
+func (d *partialArray) set(key string, val *lazyNode) error {
+ idx, err := strconv.Atoi(key)
+ if err != nil {
+ return err
+ }
+ (*d)[idx] = val
+ return nil
+}
+
+func (d *partialArray) add(key string, val *lazyNode) error {
+ if key == "-" {
+ *d = append(*d, val)
+ return nil
+ }
+
+ idx, err := strconv.Atoi(key)
+ if err != nil {
+ return err
+ }
+
+ sz := len(*d) + 1
+
+ ary := make([]*lazyNode, sz)
+
+ cur := *d
+
+ if idx >= len(ary) {
+ return fmt.Errorf("Unable to access invalid index: %d", idx)
+ }
+
+ if SupportNegativeIndices {
+ if idx < -len(ary) {
+ return fmt.Errorf("Unable to access invalid index: %d", idx)
+ }
+
+ if idx < 0 {
+ idx += len(ary)
+ }
+ }
+
+ copy(ary[0:idx], cur[0:idx])
+ ary[idx] = val
+ copy(ary[idx+1:], cur[idx:])
+
+ *d = ary
+ return nil
+}
+
+func (d *partialArray) get(key string) (*lazyNode, error) {
+ idx, err := strconv.Atoi(key)
+
+ if err != nil {
+ return nil, err
+ }
+
+ if idx >= len(*d) {
+ return nil, fmt.Errorf("Unable to access invalid index: %d", idx)
+ }
+
+ return (*d)[idx], nil
+}
+
+func (d *partialArray) remove(key string) error {
+ idx, err := strconv.Atoi(key)
+ if err != nil {
+ return err
+ }
+
+ cur := *d
+
+ if idx >= len(cur) {
+ return fmt.Errorf("Unable to access invalid index: %d", idx)
+ }
+
+ if SupportNegativeIndices {
+ if idx < -len(cur) {
+ return fmt.Errorf("Unable to access invalid index: %d", idx)
+ }
+
+ if idx < 0 {
+ idx += len(cur)
+ }
+ }
+
+ ary := make([]*lazyNode, len(cur)-1)
+
+ copy(ary[0:idx], cur[0:idx])
+ copy(ary[idx:], cur[idx+1:])
+
+ *d = ary
+ return nil
+
+}
+
+func (p Patch) add(doc *container, op operation) error {
+ path := op.path()
+
+ con, key := findObject(doc, path)
+
+ if con == nil {
+ return fmt.Errorf("jsonpatch add operation does not apply: doc is missing path: \"%s\"", path)
+ }
+
+ return con.add(key, op.value())
+}
+
+func (p Patch) remove(doc *container, op operation) error {
+ path := op.path()
+
+ con, key := findObject(doc, path)
+
+ if con == nil {
+ return fmt.Errorf("jsonpatch remove operation does not apply: doc is missing path: \"%s\"", path)
+ }
+
+ return con.remove(key)
+}
+
+func (p Patch) replace(doc *container, op operation) error {
+ path := op.path()
+
+ con, key := findObject(doc, path)
+
+ if con == nil {
+ return fmt.Errorf("jsonpatch replace operation does not apply: doc is missing path: %s", path)
+ }
+
+ _, ok := con.get(key)
+ if ok != nil {
+ return fmt.Errorf("jsonpatch replace operation does not apply: doc is missing key: %s", path)
+ }
+
+ return con.set(key, op.value())
+}
+
+func (p Patch) move(doc *container, op operation) error {
+ from := op.from()
+
+ con, key := findObject(doc, from)
+
+ if con == nil {
+ return fmt.Errorf("jsonpatch move operation does not apply: doc is missing from path: %s", from)
+ }
+
+ val, err := con.get(key)
+ if err != nil {
+ return err
+ }
+
+ err = con.remove(key)
+ if err != nil {
+ return err
+ }
+
+ path := op.path()
+
+ con, key = findObject(doc, path)
+
+ if con == nil {
+ return fmt.Errorf("jsonpatch move operation does not apply: doc is missing destination path: %s", path)
+ }
+
+ return con.add(key, val)
+}
+
+func (p Patch) test(doc *container, op operation) error {
+ path := op.path()
+
+ con, key := findObject(doc, path)
+
+ if con == nil {
+ return fmt.Errorf("jsonpatch test operation does not apply: is missing path: %s", path)
+ }
+
+ val, err := con.get(key)
+
+ if err != nil {
+ return err
+ }
+
+ if val == nil {
+ if op.value().raw == nil {
+ return nil
+ }
+ return fmt.Errorf("Testing value %s failed", path)
+ } else if op.value() == nil {
+ return fmt.Errorf("Testing value %s failed", path)
+ }
+
+ if val.equal(op.value()) {
+ return nil
+ }
+
+ return fmt.Errorf("Testing value %s failed", path)
+}
+
+func (p Patch) copy(doc *container, op operation, accumulatedCopySize *int64) error {
+ from := op.from()
+
+ con, key := findObject(doc, from)
+
+ if con == nil {
+ return fmt.Errorf("jsonpatch copy operation does not apply: doc is missing from path: %s", from)
+ }
+
+ val, err := con.get(key)
+ if err != nil {
+ return err
+ }
+
+ path := op.path()
+
+ con, key = findObject(doc, path)
+
+ if con == nil {
+ return fmt.Errorf("jsonpatch copy operation does not apply: doc is missing destination path: %s", path)
+ }
+
+ valCopy, sz, err := deepCopy(val)
+ if err != nil {
+ return err
+ }
+ (*accumulatedCopySize) += int64(sz)
+ if AccumulatedCopySizeLimit > 0 && *accumulatedCopySize > AccumulatedCopySizeLimit {
+ return NewAccumulatedCopySizeError(AccumulatedCopySizeLimit, *accumulatedCopySize)
+ }
+
+ return con.add(key, valCopy)
+}
+
+// Equal indicates if 2 JSON documents have the same structural equality.
+func Equal(a, b []byte) bool {
+ ra := make(json.RawMessage, len(a))
+ copy(ra, a)
+ la := newLazyNode(&ra)
+
+ rb := make(json.RawMessage, len(b))
+ copy(rb, b)
+ lb := newLazyNode(&rb)
+
+ return la.equal(lb)
+}
+
+// DecodePatch decodes the passed JSON document as an RFC 6902 patch.
+func DecodePatch(buf []byte) (Patch, error) {
+ var p Patch
+
+ err := json.Unmarshal(buf, &p)
+
+ if err != nil {
+ return nil, err
+ }
+
+ return p, nil
+}
+
+// Apply mutates a JSON document according to the patch, and returns the new
+// document.
+func (p Patch) Apply(doc []byte) ([]byte, error) {
+ return p.ApplyIndent(doc, "")
+}
+
+// ApplyIndent mutates a JSON document according to the patch, and returns the new
+// document indented.
+func (p Patch) ApplyIndent(doc []byte, indent string) ([]byte, error) {
+ var pd container
+ if doc[0] == '[' {
+ pd = &partialArray{}
+ } else {
+ pd = &partialDoc{}
+ }
+
+ err := json.Unmarshal(doc, pd)
+
+ if err != nil {
+ return nil, err
+ }
+
+ err = nil
+
+ var accumulatedCopySize int64
+
+ for _, op := range p {
+ switch op.kind() {
+ case "add":
+ err = p.add(&pd, op)
+ case "remove":
+ err = p.remove(&pd, op)
+ case "replace":
+ err = p.replace(&pd, op)
+ case "move":
+ err = p.move(&pd, op)
+ case "test":
+ err = p.test(&pd, op)
+ case "copy":
+ err = p.copy(&pd, op, &accumulatedCopySize)
+ default:
+ err = fmt.Errorf("Unexpected kind: %s", op.kind())
+ }
+
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ if indent != "" {
+ return json.MarshalIndent(pd, "", indent)
+ }
+
+ return json.Marshal(pd)
+}
+
+// From http://tools.ietf.org/html/rfc6901#section-4 :
+//
+// Evaluation of each reference token begins by decoding any escaped
+// character sequence. This is performed by first transforming any
+// occurrence of the sequence '~1' to '/', and then transforming any
+// occurrence of the sequence '~0' to '~'.
+
+var (
+ rfc6901Decoder = strings.NewReplacer("~1", "/", "~0", "~")
+)
+
+func decodePatchKey(k string) string {
+ return rfc6901Decoder.Replace(k)
+}
diff --git a/vendor/github.com/nlopes/slack/.gometalinter.json b/vendor/github.com/nlopes/slack/.gometalinter.json
new file mode 100644
index 000000000..5fa629d43
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/.gometalinter.json
@@ -0,0 +1,14 @@
+{
+ "DisableAll": true,
+ "Enable": [
+ "structcheck",
+ "vet",
+ "misspell",
+ "unconvert",
+ "interfacer",
+ "goimports"
+ ],
+ "Vendor": true,
+ "Exclude": ["vendor"],
+ "Deadline": "300s"
+}
diff --git a/vendor/github.com/nlopes/slack/.travis.yml b/vendor/github.com/nlopes/slack/.travis.yml
index bd0539e0c..ed99d9eff 100644
--- a/vendor/github.com/nlopes/slack/.travis.yml
+++ b/vendor/github.com/nlopes/slack/.travis.yml
@@ -1,21 +1,35 @@
language: go
-go:
- - 1.7.x
- - 1.8.x
- - 1.9.x
- - tip
+env:
+ - GO111MODULE=on
+
+install: true
before_install:
- export PATH=$HOME/gopath/bin:$PATH
+ # install gometalinter
+ - curl -L https://git.io/vp6lP | sh
script:
- - go test -race ./...
- - go test -cover ./...
+ - PATH=$PWD/bin:$PATH gometalinter ./...
+ - go test -race -cover ./...
matrix:
- allow_failures:
- - go: tip
+ allow_failures:
+ - go: tip
+ include:
+ - go: "1.7.x"
+ script: go test -v ./...
+ - go: "1.8.x"
+ script: go test -v ./...
+ - go: "1.9.x"
+ script: go test -v ./...
+ - go: "1.10.x"
+ script: go test -v ./...
+ - go: "1.11.x"
+ script: go test -v -mod=vendor ./...
+ - go: "tip"
+ script: go test -v -mod=vendor ./...
git:
depth: 10
diff --git a/vendor/github.com/nlopes/slack/CHANGELOG.md b/vendor/github.com/nlopes/slack/CHANGELOG.md
index cf0fc2cc4..63309f230 100644
--- a/vendor/github.com/nlopes/slack/CHANGELOG.md
+++ b/vendor/github.com/nlopes/slack/CHANGELOG.md
@@ -1,3 +1,8 @@
+### v0.5.0 - January 20, 2019
+full differences can be viewed using `git log --oneline --decorate --color v0.4.0..v0.5.0`
+- Breaking changes: various old struct fields have been removed or updated to match slack's api.
+- deadlock fix in RTM disconnect.
+
### v0.4.0 - October 06, 2018
full differences can be viewed using `git log --oneline --decorate --color v0.3.0..v0.4.0`
- Breaking Change: renamed ApplyMessageOption, to mark it as unsafe,
diff --git a/vendor/github.com/nlopes/slack/Gopkg.lock b/vendor/github.com/nlopes/slack/Gopkg.lock
deleted file mode 100644
index 9c33d0dc0..000000000
--- a/vendor/github.com/nlopes/slack/Gopkg.lock
+++ /dev/null
@@ -1,39 +0,0 @@
-# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
-
-
-[[projects]]
- name = "github.com/davecgh/go-spew"
- packages = ["spew"]
- revision = "346938d642f2ec3594ed81d874461961cd0faa76"
- version = "v1.1.0"
-
-[[projects]]
- name = "github.com/gorilla/websocket"
- packages = ["."]
- revision = "ea4d1f681babbce9545c9c5f3d5194a789c89f5b"
- version = "v1.2.0"
-
-[[projects]]
- name = "github.com/pkg/errors"
- packages = ["."]
- revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
- version = "v0.8.0"
-
-[[projects]]
- name = "github.com/pmezard/go-difflib"
- packages = ["difflib"]
- revision = "792786c7400a136282c1664665ae0a8db921c6c2"
- version = "v1.0.0"
-
-[[projects]]
- name = "github.com/stretchr/testify"
- packages = ["assert"]
- revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686"
- version = "v1.2.2"
-
-[solve-meta]
- analyzer-name = "dep"
- analyzer-version = 1
- inputs-digest = "596fa546322c2a1e9708a10c9f39aca2e04792b477fab86fb2899fbaab776070"
- solver-name = "gps-cdcl"
- solver-version = 1
diff --git a/vendor/github.com/nlopes/slack/Gopkg.toml b/vendor/github.com/nlopes/slack/Gopkg.toml
deleted file mode 100644
index 257870d6d..000000000
--- a/vendor/github.com/nlopes/slack/Gopkg.toml
+++ /dev/null
@@ -1,17 +0,0 @@
-ignored = ["github.com/lusis/slack-test"]
-
-[[constraint]]
- name = "github.com/gorilla/websocket"
- version = "1.2.0"
-
-[[constraint]]
- name = "github.com/stretchr/testify"
- version = "1.2.1"
-
-[[constraint]]
- name = "github.com/pkg/errors"
- version = "0.8.0"
-
-[prune]
- go-tests = true
- unused-packages = true
diff --git a/vendor/github.com/nlopes/slack/README.md b/vendor/github.com/nlopes/slack/README.md
index 849e8bdc7..a5e8e5efa 100644
--- a/vendor/github.com/nlopes/slack/README.md
+++ b/vendor/github.com/nlopes/slack/README.md
@@ -9,18 +9,10 @@ a fully managed way.
-## Change log
-Support for the EventsAPI has recently been added. It is still in its early stages but nearly all events have been added and tested (except for those events in [Developer Preview](https://api.slack.com/slack-apps-preview) mode). API stability for events is not promised at this time.
-### v0.2.0 - Feb 10, 2018
+## Changelog
-Release adds a bunch of functionality and improvements, mainly to give people a recent version to vendor against.
-
-Please check [0.2.0](https://github.com/nlopes/slack/releases/tag/v0.2.0)
-
-### CHANGELOG.md
-
- [CHANGELOG.md](https://github.com/nlopes/slack/blob/master/CHANGELOG.md) is available. Please visit it for updates.
+[CHANGELOG.md](https://github.com/nlopes/slack/blob/master/CHANGELOG.md) is available. Please visit it for updates.
## Installing
@@ -43,7 +35,7 @@ func main() {
api := slack.New("YOUR_TOKEN_HERE")
// If you set debugging, it will log all requests to the console
// Useful when encountering issues
- // api.SetDebug(true)
+ // slack.New("YOUR_TOKEN_HERE", slack.OptionDebug(true))
groups, err := api.GetGroups(false)
if err != nil {
fmt.Printf("%s\n", err)
diff --git a/vendor/github.com/nlopes/slack/admin.go b/vendor/github.com/nlopes/slack/admin.go
index a2aa7e5cb..d51426b56 100644
--- a/vendor/github.com/nlopes/slack/admin.go
+++ b/vendor/github.com/nlopes/slack/admin.go
@@ -2,28 +2,19 @@ package slack
import (
"context"
- "errors"
"fmt"
"net/url"
+ "strings"
)
-type adminResponse struct {
- OK bool `json:"ok"`
- Error string `json:"error"`
-}
-
-func adminRequest(ctx context.Context, client HTTPRequester, method string, teamName string, values url.Values, debug bool) (*adminResponse, error) {
- adminResponse := &adminResponse{}
- err := parseAdminResponse(ctx, client, method, teamName, values, adminResponse, debug)
+func (api *Client) adminRequest(ctx context.Context, method string, teamName string, values url.Values) error {
+ resp := &SlackResponse{}
+ err := parseAdminResponse(ctx, api.httpclient, method, teamName, values, resp, api)
if err != nil {
- return nil, err
+ return err
}
- if !adminResponse.OK {
- return nil, errors.New(adminResponse.Error)
- }
-
- return adminResponse, nil
+ return resp.Err()
}
// DisableUser disabled a user account, given a user ID
@@ -40,9 +31,8 @@ func (api *Client) DisableUserContext(ctx context.Context, teamName string, uid
"_attempts": {"1"},
}
- _, err := adminRequest(ctx, api.httpclient, "setInactive", teamName, values, api.debug)
- if err != nil {
- return fmt.Errorf("Failed to disable user with id '%s': %s", uid, err)
+ if err := api.adminRequest(ctx, "setInactive", teamName, values); err != nil {
+ return fmt.Errorf("failed to disable user with id '%s': %s", uid, err)
}
return nil
@@ -67,7 +57,7 @@ func (api *Client) InviteGuestContext(ctx context.Context, teamName, channel, fi
"_attempts": {"1"},
}
- _, err := adminRequest(ctx, api.httpclient, "invite", teamName, values, api.debug)
+ err := api.adminRequest(ctx, "invite", teamName, values)
if err != nil {
return fmt.Errorf("Failed to invite single-channel guest: %s", err)
}
@@ -94,7 +84,7 @@ func (api *Client) InviteRestrictedContext(ctx context.Context, teamName, channe
"_attempts": {"1"},
}
- _, err := adminRequest(ctx, api.httpclient, "invite", teamName, values, api.debug)
+ err := api.adminRequest(ctx, "invite", teamName, values)
if err != nil {
return fmt.Errorf("Failed to restricted account: %s", err)
}
@@ -118,7 +108,7 @@ func (api *Client) InviteToTeamContext(ctx context.Context, teamName, firstName,
"_attempts": {"1"},
}
- _, err := adminRequest(ctx, api.httpclient, "invite", teamName, values, api.debug)
+ err := api.adminRequest(ctx, "invite", teamName, values)
if err != nil {
return fmt.Errorf("Failed to invite to team: %s", err)
}
@@ -140,7 +130,7 @@ func (api *Client) SetRegularContext(ctx context.Context, teamName, user string)
"_attempts": {"1"},
}
- _, err := adminRequest(ctx, api.httpclient, "setRegular", teamName, values, api.debug)
+ err := api.adminRequest(ctx, "setRegular", teamName, values)
if err != nil {
return fmt.Errorf("Failed to change the user (%s) to a regular user: %s", user, err)
}
@@ -162,7 +152,7 @@ func (api *Client) SendSSOBindingEmailContext(ctx context.Context, teamName, use
"_attempts": {"1"},
}
- _, err := adminRequest(ctx, api.httpclient, "sendSSOBind", teamName, values, api.debug)
+ err := api.adminRequest(ctx, "sendSSOBind", teamName, values)
if err != nil {
return fmt.Errorf("Failed to send SSO binding email for user (%s): %s", user, err)
}
@@ -185,7 +175,7 @@ func (api *Client) SetUltraRestrictedContext(ctx context.Context, teamName, uid,
"_attempts": {"1"},
}
- _, err := adminRequest(ctx, api.httpclient, "setUltraRestricted", teamName, values, api.debug)
+ err := api.adminRequest(ctx, "setUltraRestricted", teamName, values)
if err != nil {
return fmt.Errorf("Failed to ultra-restrict account: %s", err)
}
@@ -194,22 +184,23 @@ func (api *Client) SetUltraRestrictedContext(ctx context.Context, teamName, uid,
}
// SetRestricted converts a user into a restricted account
-func (api *Client) SetRestricted(teamName, uid string) error {
- return api.SetRestrictedContext(context.Background(), teamName, uid)
+func (api *Client) SetRestricted(teamName, uid string, channelIds ...string) error {
+ return api.SetRestrictedContext(context.Background(), teamName, uid, channelIds...)
}
// SetRestrictedContext converts a user into a restricted account with a custom context
-func (api *Client) SetRestrictedContext(ctx context.Context, teamName, uid string) error {
+func (api *Client) SetRestrictedContext(ctx context.Context, teamName, uid string, channelIds ...string) error {
values := url.Values{
"user": {uid},
"token": {api.token},
"set_active": {"true"},
"_attempts": {"1"},
+ "channels": {strings.Join(channelIds, ",")},
}
- _, err := adminRequest(ctx, api.httpclient, "setRestricted", teamName, values, api.debug)
+ err := api.adminRequest(ctx, "setRestricted", teamName, values)
if err != nil {
- return fmt.Errorf("Failed to restrict account: %s", err)
+ return fmt.Errorf("failed to restrict account: %s", err)
}
return nil
diff --git a/vendor/github.com/nlopes/slack/attachments.go b/vendor/github.com/nlopes/slack/attachments.go
index 326fc010c..cf8b5c677 100644
--- a/vendor/github.com/nlopes/slack/attachments.go
+++ b/vendor/github.com/nlopes/slack/attachments.go
@@ -17,7 +17,7 @@ type AttachmentAction struct {
Name string `json:"name"` // Required.
Text string `json:"text"` // Required.
Style string `json:"style,omitempty"` // Optional. Allowed values: "default", "primary", "danger".
- Type string `json:"type"` // Required. Must be set to "button" or "select".
+ Type actionType `json:"type"` // Required. Must be set to "button" or "select".
Value string `json:"value,omitempty"` // Optional.
DataSource string `json:"data_source,omitempty"` // Optional.
MinQueryLength int `json:"min_query_length,omitempty"` // Optional. Default value is 1.
@@ -28,6 +28,11 @@ type AttachmentAction struct {
URL string `json:"url,omitempty"` // Optional.
}
+// actionType returns the type of the action
+func (a AttachmentAction) actionType() actionType {
+ return a.Type
+}
+
// AttachmentActionOption the individual option to appear in action menu.
type AttachmentActionOption struct {
Text string `json:"text"` // Required.
@@ -42,25 +47,8 @@ type AttachmentActionOptionGroup struct {
}
// AttachmentActionCallback is sent from Slack when a user clicks a button in an interactive message (aka AttachmentAction)
-type AttachmentActionCallback struct {
- Actions []AttachmentAction `json:"actions"`
- CallbackID string `json:"callback_id"`
- Team Team `json:"team"`
- Channel Channel `json:"channel"`
- User User `json:"user"`
-
- Name string `json:"name"`
- Value string `json:"value"`
-
- OriginalMessage Message `json:"original_message"`
-
- ActionTs string `json:"action_ts"`
- MessageTs string `json:"message_ts"`
- AttachmentID string `json:"attachment_id"`
- Token string `json:"token"`
- ResponseURL string `json:"response_url"`
- TriggerID string `json:"trigger_id"`
-}
+// DEPRECATED: use InteractionCallback
+type AttachmentActionCallback InteractionCallback
// ConfirmationField are used to ask users to confirm actions
type ConfirmationField struct {
diff --git a/vendor/github.com/nlopes/slack/auth.go b/vendor/github.com/nlopes/slack/auth.go
new file mode 100644
index 000000000..dc1dbcdf1
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/auth.go
@@ -0,0 +1,40 @@
+package slack
+
+import (
+ "context"
+ "net/url"
+)
+
+// AuthRevokeResponse contains our Auth response from the auth.revoke endpoint
+type AuthRevokeResponse struct {
+ SlackResponse // Contains the "ok", and "Error", if any
+ Revoked bool `json:"revoked,omitempty"`
+}
+
+// authRequest sends the actual request, and unmarshals the response
+func (api *Client) authRequest(ctx context.Context, path string, values url.Values) (*AuthRevokeResponse, error) {
+ response := &AuthRevokeResponse{}
+ err := api.postMethod(ctx, path, values, response)
+ if err != nil {
+ return nil, err
+ }
+
+ return response, response.Err()
+}
+
+// SendAuthRevoke will send a revocation for our token
+func (api *Client) SendAuthRevoke(token string) (*AuthRevokeResponse, error) {
+ return api.SendAuthRevokeContext(context.Background(), token)
+}
+
+// SendAuthRevokeContext will retrieve the satus from api.test
+func (api *Client) SendAuthRevokeContext(ctx context.Context, token string) (*AuthRevokeResponse, error) {
+ if token == "" {
+ token = api.token
+ }
+ values := url.Values{
+ "token": {token},
+ }
+
+ return api.authRequest(ctx, "auth.revoke", values)
+}
diff --git a/vendor/github.com/nlopes/slack/backoff.go b/vendor/github.com/nlopes/slack/backoff.go
index 197bce2e5..2ba697e7e 100644
--- a/vendor/github.com/nlopes/slack/backoff.go
+++ b/vendor/github.com/nlopes/slack/backoff.go
@@ -1,7 +1,6 @@
package slack
import (
- "math"
"math/rand"
"time"
)
@@ -14,41 +13,42 @@ import (
// conjunction with the time package.
type backoff struct {
attempts int
- //Factor is the multiplying factor for each increment step
- Factor float64
- //Jitter eases contention by randomizing backoff steps
- Jitter bool
- //Min and Max are the minimum and maximum values of the counter
- Min, Max time.Duration
+ // Initial value to scale out
+ Initial time.Duration
+ // Jitter value randomizes an additional delay between 0 and Jitter
+ Jitter time.Duration
+ // Max maximum values of the backoff
+ Max time.Duration
}
// Returns the current value of the counter and then multiplies it
// Factor
-func (b *backoff) Duration() time.Duration {
- //Zero-values are nonsensical, so we use
- //them to apply defaults
- if b.Min == 0 {
- b.Min = 100 * time.Millisecond
- }
+func (b *backoff) Duration() (dur time.Duration) {
+ // Zero-values are nonsensical, so we use
+ // them to apply defaults
if b.Max == 0 {
b.Max = 10 * time.Second
}
- if b.Factor == 0 {
- b.Factor = 2
+
+ if b.Initial == 0 {
+ b.Initial = 100 * time.Millisecond
}
- //calculate this duration
- dur := float64(b.Min) * math.Pow(b.Factor, float64(b.attempts))
- if b.Jitter {
- dur = rand.Float64()*(dur-float64(b.Min)) + float64(b.Min)
+
+ // calculate this duration
+ if dur = time.Duration(1 << uint(b.attempts)); dur > 0 {
+ dur = dur * b.Initial
+ } else {
+ dur = b.Max
}
- //cap!
- if dur > float64(b.Max) {
- return b.Max
+
+ if b.Jitter > 0 {
+ dur = dur + time.Duration(rand.Intn(int(b.Jitter)))
}
- //bump attempts count
+
+ // bump attempts count
b.attempts++
- //return as a time.Duration
- return time.Duration(dur)
+
+ return dur
}
//Resets the current value of the counter back to Min
diff --git a/vendor/github.com/nlopes/slack/block.go b/vendor/github.com/nlopes/slack/block.go
new file mode 100644
index 000000000..1fc7fecec
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/block.go
@@ -0,0 +1,71 @@
+package slack
+
+// @NOTE: Blocks are in beta and subject to change.
+
+// More Information: https://api.slack.com/block-kit
+
+// MessageBlockType defines a named string type to define each block type
+// as a constant for use within the package.
+type MessageBlockType string
+
+const (
+ MBTSection MessageBlockType = "section"
+ MBTDivider MessageBlockType = "divider"
+ MBTImage MessageBlockType = "image"
+ MBTAction MessageBlockType = "actions"
+ MBTContext MessageBlockType = "context"
+)
+
+// Block defines an interface all block types should implement
+// to ensure consistency between blocks.
+type Block interface {
+ BlockType() MessageBlockType
+}
+
+// Blocks is a convenience struct defined to allow dynamic unmarshalling of
+// the "blocks" value in Slack's JSON response, which varies depending on block type
+type Blocks struct {
+ BlockSet []Block `json:"blocks,omitempty"`
+}
+
+// BlockAction is the action callback sent when a block is interacted with
+type BlockAction struct {
+ ActionID string `json:"action_id"`
+ BlockID string `json:"block_id"`
+ Type actionType `json:"type"`
+ Text TextBlockObject `json:"text"`
+ Value string `json:"value"`
+ ActionTs string `json:"action_ts"`
+ SelectedOption OptionBlockObject `json:"selected_option"`
+ SelectedUser string `json:"selected_user"`
+ SelectedChannel string `json:"selected_channel"`
+ SelectedConversation string `json:"selected_conversation"`
+ SelectedDate string `json:"selected_date"`
+ InitialOption OptionBlockObject `json:"initial_option"`
+ InitialUser string `json:"initial_user"`
+ InitialChannel string `json:"initial_channel"`
+ InitialConversation string `json:"initial_conversation"`
+ InitialDate string `json:"initial_date"`
+}
+
+// actionType returns the type of the action
+func (b BlockAction) actionType() actionType {
+ return b.Type
+}
+
+// NewBlockMessage creates a new Message that contains one or more blocks to be displayed
+func NewBlockMessage(blocks ...Block) Message {
+ return Message{
+ Msg: Msg{
+ Blocks: Blocks{
+ BlockSet: blocks,
+ },
+ },
+ }
+}
+
+// AddBlockMessage appends a block to the end of the existing list of blocks
+func AddBlockMessage(message Message, newBlk Block) Message {
+ message.Msg.Blocks.BlockSet = append(message.Msg.Blocks.BlockSet, newBlk)
+ return message
+}
diff --git a/vendor/github.com/nlopes/slack/block_action.go b/vendor/github.com/nlopes/slack/block_action.go
new file mode 100644
index 000000000..fe46a95cf
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/block_action.go
@@ -0,0 +1,26 @@
+package slack
+
+// ActionBlock defines data that is used to hold interactive elements.
+//
+// More Information: https://api.slack.com/reference/messaging/blocks#actions
+type ActionBlock struct {
+ Type MessageBlockType `json:"type"`
+ BlockID string `json:"block_id,omitempty"`
+ Elements BlockElements `json:"elements"`
+}
+
+// BlockType returns the type of the block
+func (s ActionBlock) BlockType() MessageBlockType {
+ return s.Type
+}
+
+// NewActionBlock returns a new instance of an Action Block
+func NewActionBlock(blockID string, elements ...BlockElement) *ActionBlock {
+ return &ActionBlock{
+ Type: MBTAction,
+ BlockID: blockID,
+ Elements: BlockElements{
+ ElementSet: elements,
+ },
+ }
+}
diff --git a/vendor/github.com/nlopes/slack/block_context.go b/vendor/github.com/nlopes/slack/block_context.go
new file mode 100644
index 000000000..c37bf27e9
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/block_context.go
@@ -0,0 +1,32 @@
+package slack
+
+// ContextBlock defines data that is used to display message context, which can
+// include both images and text.
+//
+// More Information: https://api.slack.com/reference/messaging/blocks#actions
+type ContextBlock struct {
+ Type MessageBlockType `json:"type"`
+ BlockID string `json:"block_id,omitempty"`
+ ContextElements ContextElements `json:"elements"`
+}
+
+// BlockType returns the type of the block
+func (s ContextBlock) BlockType() MessageBlockType {
+ return s.Type
+}
+
+type ContextElements struct {
+ Elements []MixedElement
+}
+
+// NewContextBlock returns a new instance of a context block
+func NewContextBlock(blockID string, mixedElements ...MixedElement) *ContextBlock {
+ elements := ContextElements{
+ Elements: mixedElements,
+ }
+ return &ContextBlock{
+ Type: MBTContext,
+ BlockID: blockID,
+ ContextElements: elements,
+ }
+}
diff --git a/vendor/github.com/nlopes/slack/block_conv.go b/vendor/github.com/nlopes/slack/block_conv.go
new file mode 100644
index 000000000..619867ea2
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/block_conv.go
@@ -0,0 +1,303 @@
+package slack
+
+import (
+ "encoding/json"
+
+ "github.com/pkg/errors"
+)
+
+type sumtype struct {
+ TypeVal string `json:"type"`
+}
+
+// MarshalJSON implements the Marshaller interface for Blocks so that any JSON
+// marshalling is delegated and proper type determination can be made before marshal
+func (b Blocks) MarshalJSON() ([]byte, error) {
+ bytes, err := json.Marshal(b.BlockSet)
+ if err != nil {
+ return nil, err
+ }
+
+ return bytes, nil
+}
+
+// UnmarshalJSON implements the Unmarshaller interface for Blocks, so that any JSON
+// unmarshalling is delegated and proper type determination can be made before unmarshal
+func (b *Blocks) UnmarshalJSON(data []byte) error {
+ var raw []json.RawMessage
+
+ if string(data) == "{}" {
+ return nil
+ }
+
+ err := json.Unmarshal(data, &raw)
+ if err != nil {
+ return err
+ }
+
+ var blocks Blocks
+ for _, r := range raw {
+ s := sumtype{}
+ err := json.Unmarshal(r, &s)
+ if err != nil {
+ return err
+ }
+
+ var blockType string
+ if s.TypeVal != "" {
+ blockType = s.TypeVal
+ }
+
+ var block Block
+ switch blockType {
+ case "actions":
+ block = &ActionBlock{}
+ case "context":
+ block = &ContextBlock{}
+ case "divider":
+ block = &DividerBlock{}
+ case "image":
+ block = &ImageBlock{}
+ case "section":
+ block = &SectionBlock{}
+ default:
+ return errors.New("unsupported block type")
+ }
+
+ err = json.Unmarshal(r, block)
+ if err != nil {
+ return err
+ }
+
+ blocks.BlockSet = append(blocks.BlockSet, block)
+ }
+
+ *b = blocks
+ return nil
+}
+
+// MarshalJSON implements the Marshaller interface for BlockElements so that any JSON
+// marshalling is delegated and proper type determination can be made before marshal
+func (b *BlockElements) MarshalJSON() ([]byte, error) {
+ bytes, err := json.Marshal(b.ElementSet)
+ if err != nil {
+ return nil, err
+ }
+
+ return bytes, nil
+}
+
+// UnmarshalJSON implements the Unmarshaller interface for BlockElements, so that any JSON
+// unmarshalling is delegated and proper type determination can be made before unmarshal
+func (b *BlockElements) UnmarshalJSON(data []byte) error {
+ var raw []json.RawMessage
+
+ if string(data) == "{}" {
+ return nil
+ }
+
+ err := json.Unmarshal(data, &raw)
+ if err != nil {
+ return err
+ }
+
+ var blockElements BlockElements
+ for _, r := range raw {
+ s := sumtype{}
+ err := json.Unmarshal(r, &s)
+ if err != nil {
+ return err
+ }
+
+ var blockElementType string
+ if s.TypeVal != "" {
+ blockElementType = s.TypeVal
+ }
+
+ var blockElement BlockElement
+ switch blockElementType {
+ case "image":
+ blockElement = &ImageBlockElement{}
+ case "button":
+ blockElement = &ButtonBlockElement{}
+ case "overflow":
+ blockElement = &OverflowBlockElement{}
+ case "datepicker":
+ blockElement = &DatePickerBlockElement{}
+ case "static_select", "external_select", "users_select", "conversations_select", "channels_select":
+ blockElement = &SelectBlockElement{}
+ default:
+ return errors.New("unsupported block element type")
+ }
+
+ err = json.Unmarshal(r, blockElement)
+ if err != nil {
+ return err
+ }
+
+ blockElements.ElementSet = append(blockElements.ElementSet, blockElement)
+ }
+
+ *b = blockElements
+ return nil
+}
+
+// MarshalJSON implements the Marshaller interface for Accessory so that any JSON
+// marshalling is delegated and proper type determination can be made before marshal
+func (a *Accessory) MarshalJSON() ([]byte, error) {
+ bytes, err := json.Marshal(toBlockElement(a))
+ if err != nil {
+ return nil, err
+ }
+
+ return bytes, nil
+}
+
+// UnmarshalJSON implements the Unmarshaller interface for Accessory, so that any JSON
+// unmarshalling is delegated and proper type determination can be made before unmarshal
+func (a *Accessory) UnmarshalJSON(data []byte) error {
+ var r json.RawMessage
+
+ if string(data) == "{\"accessory\":null}" {
+ return nil
+ }
+
+ err := json.Unmarshal(data, &r)
+ if err != nil {
+ return err
+ }
+
+ s := sumtype{}
+ err = json.Unmarshal(r, &s)
+ if err != nil {
+ return err
+ }
+
+ var blockElementType string
+ if s.TypeVal != "" {
+ blockElementType = s.TypeVal
+ }
+
+ switch blockElementType {
+ case "image":
+ element, err := unmarshalBlockElement(r, &ImageBlockElement{})
+ if err != nil {
+ return err
+ }
+ a.ImageElement = element.(*ImageBlockElement)
+ case "button":
+ element, err := unmarshalBlockElement(r, &ButtonBlockElement{})
+ if err != nil {
+ return err
+ }
+ a.ButtonElement = element.(*ButtonBlockElement)
+ case "overflow":
+ element, err := unmarshalBlockElement(r, &OverflowBlockElement{})
+ if err != nil {
+ return err
+ }
+ a.OverflowElement = element.(*OverflowBlockElement)
+ case "datepicker":
+ element, err := unmarshalBlockElement(r, &DatePickerBlockElement{})
+ if err != nil {
+ return err
+ }
+ a.DatePickerElement = element.(*DatePickerBlockElement)
+ case "static_select":
+ element, err := unmarshalBlockElement(r, &SelectBlockElement{})
+ if err != nil {
+ return err
+ }
+ a.SelectElement = element.(*SelectBlockElement)
+ }
+
+ return nil
+}
+
+func unmarshalBlockElement(r json.RawMessage, element BlockElement) (BlockElement, error) {
+ err := json.Unmarshal(r, element)
+ if err != nil {
+ return nil, err
+ }
+ return element, nil
+}
+
+func toBlockElement(element *Accessory) BlockElement {
+ if element.ImageElement != nil {
+ return element.ImageElement
+ }
+ if element.ButtonElement != nil {
+ return element.ButtonElement
+ }
+ if element.OverflowElement != nil {
+ return element.OverflowElement
+ }
+ if element.DatePickerElement != nil {
+ return element.DatePickerElement
+ }
+ if element.SelectElement != nil {
+ return element.SelectElement
+ }
+
+ return nil
+}
+
+// MarshalJSON implements the Marshaller interface for ContextElements so that any JSON
+// marshalling is delegated and proper type determination can be made before marshal
+func (e *ContextElements) MarshalJSON() ([]byte, error) {
+ bytes, err := json.Marshal(e.Elements)
+ if err != nil {
+ return nil, err
+ }
+
+ return bytes, nil
+}
+
+// UnmarshalJSON implements the Unmarshaller interface for ContextElements, so that any JSON
+// unmarshalling is delegated and proper type determination can be made before unmarshal
+func (e *ContextElements) UnmarshalJSON(data []byte) error {
+ var raw []json.RawMessage
+
+ if string(data) == "{\"elements\":null}" {
+ return nil
+ }
+
+ err := json.Unmarshal(data, &raw)
+ if err != nil {
+ return err
+ }
+
+ for _, r := range raw {
+ s := sumtype{}
+ err := json.Unmarshal(r, &s)
+ if err != nil {
+ return err
+ }
+
+ var contextElementType string
+ if s.TypeVal != "" {
+ contextElementType = s.TypeVal
+ }
+
+ switch contextElementType {
+ case PlainTextType, MarkdownType:
+ elem, err := unmarshalBlockObject(r, &TextBlockObject{})
+ if err != nil {
+ return err
+ }
+
+ e.Elements = append(e.Elements, elem.(*TextBlockObject))
+ case "image":
+ elem, err := unmarshalBlockElement(r, &ImageBlockElement{})
+ if err != nil {
+ return err
+ }
+
+ e.Elements = append(e.Elements, elem.(*ImageBlockElement))
+ default:
+ return errors.New("unsupported context element type")
+ }
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/nlopes/slack/block_divider.go b/vendor/github.com/nlopes/slack/block_divider.go
new file mode 100644
index 000000000..2d442ba11
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/block_divider.go
@@ -0,0 +1,22 @@
+package slack
+
+// DividerBlock for displaying a divider line between blocks (similar to
tag in html)
+//
+// More Information: https://api.slack.com/reference/messaging/blocks#divider
+type DividerBlock struct {
+ Type MessageBlockType `json:"type"`
+ BlockID string `json:"block_id,omitempty"`
+}
+
+// BlockType returns the type of the block
+func (s DividerBlock) BlockType() MessageBlockType {
+ return s.Type
+}
+
+// NewDividerBlock returns a new instance of a divider block
+func NewDividerBlock() *DividerBlock {
+ return &DividerBlock{
+ Type: MBTDivider,
+ }
+
+}
diff --git a/vendor/github.com/nlopes/slack/block_element.go b/vendor/github.com/nlopes/slack/block_element.go
new file mode 100644
index 000000000..c62ba99c9
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/block_element.go
@@ -0,0 +1,238 @@
+package slack
+
+// https://api.slack.com/reference/messaging/block-elements
+
+const (
+ METImage MessageElementType = "image"
+ METButton MessageElementType = "button"
+ METOverflow MessageElementType = "overflow"
+ METDatepicker MessageElementType = "datepicker"
+
+ MixedElementImage MixedElementType = "mixed_image"
+ MixedElementText MixedElementType = "mixed_text"
+
+ OptTypeStatic string = "static_select"
+ OptTypeExternal string = "external_select"
+ OptTypeUser string = "users_select"
+ OptTypeConversations string = "conversations_select"
+ OptTypeChannels string = "channels_select"
+)
+
+type MessageElementType string
+type MixedElementType string
+
+// BlockElement defines an interface that all block element types should implement.
+type BlockElement interface {
+ ElementType() MessageElementType
+}
+
+type MixedElement interface {
+ MixedElementType() MixedElementType
+}
+
+type Accessory struct {
+ ImageElement *ImageBlockElement
+ ButtonElement *ButtonBlockElement
+ OverflowElement *OverflowBlockElement
+ DatePickerElement *DatePickerBlockElement
+ SelectElement *SelectBlockElement
+}
+
+// NewAccessory returns a new Accessory for a given block element
+func NewAccessory(element BlockElement) *Accessory {
+ switch element.(type) {
+ case *ImageBlockElement:
+ return &Accessory{ImageElement: element.(*ImageBlockElement)}
+ case *ButtonBlockElement:
+ return &Accessory{ButtonElement: element.(*ButtonBlockElement)}
+ case *OverflowBlockElement:
+ return &Accessory{OverflowElement: element.(*OverflowBlockElement)}
+ case *DatePickerBlockElement:
+ return &Accessory{DatePickerElement: element.(*DatePickerBlockElement)}
+ case *SelectBlockElement:
+ return &Accessory{SelectElement: element.(*SelectBlockElement)}
+ }
+
+ return nil
+}
+
+// BlockElements is a convenience struct defined to allow dynamic unmarshalling of
+// the "elements" value in Slack's JSON response, which varies depending on BlockElement type
+type BlockElements struct {
+ ElementSet []BlockElement `json:"elements,omitempty"`
+}
+
+// ImageBlockElement An element to insert an image - this element can be used
+// in section and context blocks only. If you want a block with only an image
+// in it, you're looking for the image block.
+//
+// More Information: https://api.slack.com/reference/messaging/block-elements#image
+type ImageBlockElement struct {
+ Type MessageElementType `json:"type"`
+ ImageURL string `json:"image_url"`
+ AltText string `json:"alt_text"`
+}
+
+// ElementType returns the type of the Element
+func (s ImageBlockElement) ElementType() MessageElementType {
+ return s.Type
+}
+
+func (s ImageBlockElement) MixedElementType() MixedElementType {
+ return MixedElementImage
+}
+
+// NewImageBlockElement returns a new instance of an image block element
+func NewImageBlockElement(imageURL, altText string) *ImageBlockElement {
+ return &ImageBlockElement{
+ Type: METImage,
+ ImageURL: imageURL,
+ AltText: altText,
+ }
+}
+
+type Style string
+
+const (
+ StyleDefault Style = "default"
+ StylePrimary Style = "primary"
+ StyleDanger Style = "danger"
+)
+
+// ButtonBlockElement defines an interactive element that inserts a button. The
+// button can be a trigger for anything from opening a simple link to starting
+// a complex workflow.
+//
+// More Information: https://api.slack.com/reference/messaging/block-elements#button
+type ButtonBlockElement struct {
+ Type MessageElementType `json:"type,omitempty"`
+ Text *TextBlockObject `json:"text"`
+ ActionID string `json:"action_id,omitempty"`
+ URL string `json:"url,omitempty"`
+ Value string `json:"value,omitempty"`
+ Confirm *ConfirmationBlockObject `json:"confirm,omitempty"`
+ Style Style `json:"style,omitempty"`
+}
+
+// ElementType returns the type of the element
+func (s ButtonBlockElement) ElementType() MessageElementType {
+ return s.Type
+}
+
+// add styling to button object
+func (s *ButtonBlockElement) WithStyle(style Style) {
+ s.Style = style
+}
+
+// NewButtonBlockElement returns an instance of a new button element to be used within a block
+func NewButtonBlockElement(actionID, value string, text *TextBlockObject) *ButtonBlockElement {
+ return &ButtonBlockElement{
+ Type: METButton,
+ ActionID: actionID,
+ Text: text,
+ Value: value,
+ }
+}
+
+// SelectBlockElement defines the simplest form of select menu, with a static list
+// of options passed in when defining the element.
+//
+// More Information: https://api.slack.com/reference/messaging/block-elements#select
+type SelectBlockElement struct {
+ Type string `json:"type,omitempty"`
+ Placeholder *TextBlockObject `json:"placeholder,omitempty"`
+ ActionID string `json:"action_id,omitempty"`
+ Options []*OptionBlockObject `json:"options,omitempty"`
+ OptionGroups []*OptionGroupBlockObject `json:"option_groups,omitempty"`
+ InitialOption *OptionBlockObject `json:"initial_option,omitempty"`
+ InitialUser string `json:"initial_user,omitempty"`
+ InitialConversation string `json:"initial_conversation,omitempty"`
+ InitialChannel string `json:"initial_channel,omitempty"`
+ MinQueryLength int `json:"min_query_length,omitempty"`
+ Confirm *ConfirmationBlockObject `json:"confirm,omitempty"`
+}
+
+// ElementType returns the type of the Element
+func (s SelectBlockElement) ElementType() MessageElementType {
+ return MessageElementType(s.Type)
+}
+
+// NewOptionsSelectBlockElement returns a new instance of SelectBlockElement for use with
+// the Options object only.
+func NewOptionsSelectBlockElement(optType string, placeholder *TextBlockObject, actionID string, options ...*OptionBlockObject) *SelectBlockElement {
+ return &SelectBlockElement{
+ Type: optType,
+ Placeholder: placeholder,
+ ActionID: actionID,
+ Options: options,
+ }
+}
+
+// NewOptionsGroupSelectBlockElement returns a new instance of SelectBlockElement for use with
+// the Options object only.
+func NewOptionsGroupSelectBlockElement(
+ optType string,
+ placeholder *TextBlockObject,
+ actionID string,
+ optGroups ...*OptionGroupBlockObject,
+) *SelectBlockElement {
+ return &SelectBlockElement{
+ Type: optType,
+ Placeholder: placeholder,
+ ActionID: actionID,
+ OptionGroups: optGroups,
+ }
+}
+
+// OverflowBlockElement defines the fields needed to use an overflow element.
+// And Overflow Element is like a cross between a button and a select menu -
+// when a user clicks on this overflow button, they will be presented with a
+// list of options to choose from.
+//
+// More Information: https://api.slack.com/reference/messaging/block-elements#overflow
+type OverflowBlockElement struct {
+ Type MessageElementType `json:"type"`
+ ActionID string `json:"action_id,omitempty"`
+ Options []*OptionBlockObject `json:"options"`
+ Confirm *ConfirmationBlockObject `json:"confirm,omitempty"`
+}
+
+// ElementType returns the type of the Element
+func (s OverflowBlockElement) ElementType() MessageElementType {
+ return s.Type
+}
+
+// NewOverflowBlockElement returns an instance of a new Overflow Block Element
+func NewOverflowBlockElement(actionID string, options ...*OptionBlockObject) *OverflowBlockElement {
+ return &OverflowBlockElement{
+ Type: METOverflow,
+ ActionID: actionID,
+ Options: options,
+ }
+}
+
+// DatePickerBlockElement defines an element which lets users easily select a
+// date from a calendar style UI. Date picker elements can be used inside of
+// section and actions blocks.
+//
+// More Information: https://api.slack.com/reference/messaging/block-elements#datepicker
+type DatePickerBlockElement struct {
+ Type MessageElementType `json:"type"`
+ ActionID string `json:"action_id"`
+ Placeholder *TextBlockObject `json:"placeholder,omitempty"`
+ InitialDate string `json:"initial_date,omitempty"`
+ Confirm *ConfirmationBlockObject `json:"confirm,omitempty"`
+}
+
+// ElementType returns the type of the Element
+func (s DatePickerBlockElement) ElementType() MessageElementType {
+ return s.Type
+}
+
+// NewDatePickerBlockElement returns an instance of a date picker element
+func NewDatePickerBlockElement(actionID string) *DatePickerBlockElement {
+ return &DatePickerBlockElement{
+ Type: METDatepicker,
+ ActionID: actionID,
+ }
+}
diff --git a/vendor/github.com/nlopes/slack/block_image.go b/vendor/github.com/nlopes/slack/block_image.go
new file mode 100644
index 000000000..6de3f63a2
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/block_image.go
@@ -0,0 +1,28 @@
+package slack
+
+// ImageBlock defines data required to display an image as a block element
+//
+// More Information: https://api.slack.com/reference/messaging/blocks#image
+type ImageBlock struct {
+ Type MessageBlockType `json:"type"`
+ ImageURL string `json:"image_url"`
+ AltText string `json:"alt_text"`
+ BlockID string `json:"block_id,omitempty"`
+ Title *TextBlockObject `json:"title"`
+}
+
+// BlockType returns the type of the block
+func (s ImageBlock) BlockType() MessageBlockType {
+ return s.Type
+}
+
+// NewImageBlock returns an instance of a new Image Block type
+func NewImageBlock(imageURL, altText, blockID string, title *TextBlockObject) *ImageBlock {
+ return &ImageBlock{
+ Type: MBTImage,
+ ImageURL: imageURL,
+ AltText: altText,
+ BlockID: blockID,
+ Title: title,
+ }
+}
diff --git a/vendor/github.com/nlopes/slack/block_object.go b/vendor/github.com/nlopes/slack/block_object.go
new file mode 100644
index 000000000..0deb183c8
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/block_object.go
@@ -0,0 +1,215 @@
+package slack
+
+import (
+ "encoding/json"
+)
+
+// Block Objects are also known as Composition Objects
+//
+// For more information: https://api.slack.com/reference/messaging/composition-objects
+
+// BlockObject defines an interface that all block object types should
+// implement.
+// @TODO: Is this interface needed?
+
+// blockObject object types
+const (
+ MarkdownType = "mrkdwn"
+ PlainTextType = "plain_text"
+ // The following objects don't actually have types and their corresponding
+ // const values are just for internal use
+ motConfirmation = "confirm"
+ motOption = "option"
+ motOptionGroup = "option_group"
+)
+
+type MessageObjectType string
+
+type blockObject interface {
+ validateType() MessageObjectType
+}
+
+type BlockObjects struct {
+ TextObjects []*TextBlockObject
+ ConfirmationObjects []*ConfirmationBlockObject
+ OptionObjects []*OptionBlockObject
+ OptionGroupObjects []*OptionGroupBlockObject
+}
+
+// UnmarshalJSON implements the Unmarshaller interface for BlockObjects, so that any JSON
+// unmarshalling is delegated and proper type determination can be made before unmarshal
+func (b *BlockObjects) UnmarshalJSON(data []byte) error {
+ var raw []json.RawMessage
+ err := json.Unmarshal(data, &raw)
+ if err != nil {
+ return err
+ }
+
+ for _, r := range raw {
+ var obj map[string]interface{}
+ err := json.Unmarshal(r, &obj)
+ if err != nil {
+ return err
+ }
+
+ blockObjectType := getBlockObjectType(obj)
+
+ switch blockObjectType {
+ case PlainTextType, MarkdownType:
+ object, err := unmarshalBlockObject(r, &TextBlockObject{})
+ if err != nil {
+ return err
+ }
+ b.TextObjects = append(b.TextObjects, object.(*TextBlockObject))
+ case motConfirmation:
+ object, err := unmarshalBlockObject(r, &ConfirmationBlockObject{})
+ if err != nil {
+ return err
+ }
+ b.ConfirmationObjects = append(b.ConfirmationObjects, object.(*ConfirmationBlockObject))
+ case motOption:
+ object, err := unmarshalBlockObject(r, &OptionBlockObject{})
+ if err != nil {
+ return err
+ }
+ b.OptionObjects = append(b.OptionObjects, object.(*OptionBlockObject))
+ case motOptionGroup:
+ object, err := unmarshalBlockObject(r, &OptionGroupBlockObject{})
+ if err != nil {
+ return err
+ }
+ b.OptionGroupObjects = append(b.OptionGroupObjects, object.(*OptionGroupBlockObject))
+
+ }
+ }
+
+ return nil
+}
+
+// Ideally would have a better way to identify the block objects for
+// type casting at time of unmarshalling, should be adapted if possible
+// to accomplish in a more reliable manner.
+func getBlockObjectType(obj map[string]interface{}) string {
+ if t, ok := obj["type"].(string); ok {
+ return t
+ }
+ if _, ok := obj["confirm"].(string); ok {
+ return "confirm"
+ }
+ if _, ok := obj["options"].(string); ok {
+ return "option_group"
+ }
+ if _, ok := obj["text"].(string); ok {
+ if _, ok := obj["value"].(string); ok {
+ return "option"
+ }
+ }
+ return ""
+}
+
+func unmarshalBlockObject(r json.RawMessage, object blockObject) (blockObject, error) {
+ err := json.Unmarshal(r, object)
+ if err != nil {
+ return nil, err
+ }
+ return object, nil
+}
+
+// TextBlockObject defines a text element object to be used with blocks
+//
+// More Information: https://api.slack.com/reference/messaging/composition-objects#text
+type TextBlockObject struct {
+ Type string `json:"type"`
+ Text string `json:"text"`
+ Emoji bool `json:"emoji,omitempty"`
+ Verbatim bool `json:"verbatim,omitempty"`
+}
+
+// validateType enforces block objects for element and block parameters
+func (s TextBlockObject) validateType() MessageObjectType {
+ return MessageObjectType(s.Type)
+}
+
+// validateType enforces block objects for element and block parameters
+func (s TextBlockObject) MixedElementType() MixedElementType {
+ return MixedElementText
+}
+
+// NewTextBlockObject returns an instance of a new Text Block Object
+func NewTextBlockObject(elementType, text string, emoji, verbatim bool) *TextBlockObject {
+ return &TextBlockObject{
+ Type: elementType,
+ Text: text,
+ Emoji: emoji,
+ Verbatim: verbatim,
+ }
+}
+
+// ConfirmationBlockObject defines a dialog that provides a confirmation step to
+// any interactive element. This dialog will ask the user to confirm their action by
+// offering a confirm and deny buttons.
+//
+// More Information: https://api.slack.com/reference/messaging/composition-objects#confirm
+type ConfirmationBlockObject struct {
+ Title *TextBlockObject `json:"title"`
+ Text *TextBlockObject `json:"text"`
+ Confirm *TextBlockObject `json:"confirm"`
+ Deny *TextBlockObject `json:"deny"`
+}
+
+// validateType enforces block objects for element and block parameters
+func (s ConfirmationBlockObject) validateType() MessageObjectType {
+ return motConfirmation
+}
+
+// NewConfirmationBlockObject returns an instance of a new Confirmation Block Object
+func NewConfirmationBlockObject(title, text, confirm, deny *TextBlockObject) *ConfirmationBlockObject {
+ return &ConfirmationBlockObject{
+ Title: title,
+ Text: text,
+ Confirm: confirm,
+ Deny: deny,
+ }
+}
+
+// OptionBlockObject represents a single selectable item in a select menu
+//
+// More Information: https://api.slack.com/reference/messaging/composition-objects#option
+type OptionBlockObject struct {
+ Text *TextBlockObject `json:"text"`
+ Value string `json:"value"`
+}
+
+// NewOptionBlockObject returns an instance of a new Option Block Element
+func NewOptionBlockObject(value string, text *TextBlockObject) *OptionBlockObject {
+ return &OptionBlockObject{
+ Text: text,
+ Value: value,
+ }
+}
+
+// validateType enforces block objects for element and block parameters
+func (s OptionBlockObject) validateType() MessageObjectType {
+ return motOption
+}
+
+// OptionGroupBlockObject Provides a way to group options in a select menu.
+//
+// More Information: https://api.slack.com/reference/messaging/composition-objects#option-group
+type OptionGroupBlockObject struct {
+ Label *TextBlockObject `json:"label,omitempty"`
+ Options []*OptionBlockObject `json:"options"`
+}
+
+// validateType enforces block objects for element and block parameters
+func (s OptionGroupBlockObject) validateType() MessageObjectType {
+ return motOptionGroup
+}
+
+// NewOptionGroupBlockElement returns an instance of a new option group block element
+func NewOptionGroupBlockElement(label *TextBlockObject, options ...*OptionBlockObject) *OptionGroupBlockObject {
+ return &OptionGroupBlockObject{
+ Label: label,
+ Options: options,
+ }
+}
diff --git a/vendor/github.com/nlopes/slack/block_section.go b/vendor/github.com/nlopes/slack/block_section.go
new file mode 100644
index 000000000..01ffd5a1d
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/block_section.go
@@ -0,0 +1,42 @@
+package slack
+
+// SectionBlock defines a new block of type section
+//
+// More Information: https://api.slack.com/reference/messaging/blocks#section
+type SectionBlock struct {
+ Type MessageBlockType `json:"type"`
+ Text *TextBlockObject `json:"text,omitempty"`
+ BlockID string `json:"block_id,omitempty"`
+ Fields []*TextBlockObject `json:"fields,omitempty"`
+ Accessory *Accessory `json:"accessory,omitempty"`
+}
+
+// BlockType returns the type of the block
+func (s SectionBlock) BlockType() MessageBlockType {
+ return s.Type
+}
+
+// SectionBlockOption allows configuration of options for a new section block
+type SectionBlockOption func(*SectionBlock)
+
+func SectionBlockOptionBlockID(blockID string) SectionBlockOption {
+ return func(block *SectionBlock) {
+ block.BlockID = blockID
+ }
+}
+
+// NewSectionBlock returns a new instance of a section block to be rendered
+func NewSectionBlock(textObj *TextBlockObject, fields []*TextBlockObject, accessory *Accessory, options ...SectionBlockOption) *SectionBlock {
+ block := SectionBlock{
+ Type: MBTSection,
+ Text: textObj,
+ Fields: fields,
+ Accessory: accessory,
+ }
+
+ for _, option := range options {
+ option(&block)
+ }
+
+ return &block
+}
diff --git a/vendor/github.com/nlopes/slack/bots.go b/vendor/github.com/nlopes/slack/bots.go
index 92570a049..06e03483b 100644
--- a/vendor/github.com/nlopes/slack/bots.go
+++ b/vendor/github.com/nlopes/slack/bots.go
@@ -2,7 +2,6 @@ package slack
import (
"context"
- "errors"
"net/url"
)
@@ -19,15 +18,17 @@ type botResponseFull struct {
SlackResponse
}
-func botRequest(ctx context.Context, client HTTPRequester, path string, values url.Values, debug bool) (*botResponseFull, error) {
+func (api *Client) botRequest(ctx context.Context, path string, values url.Values) (*botResponseFull, error) {
response := &botResponseFull{}
- err := postSlackMethod(ctx, client, path, values, response, debug)
+ err := api.postMethod(ctx, path, values, response)
if err != nil {
return nil, err
}
- if !response.Ok {
- return nil, errors.New(response.Error)
+
+ if err := response.Err(); err != nil {
+ return nil, err
}
+
return response, nil
}
@@ -43,7 +44,7 @@ func (api *Client) GetBotInfoContext(ctx context.Context, bot string) (*Bot, err
"bot": {bot},
}
- response, err := botRequest(ctx, api.httpclient, "bots.info", values, api.debug)
+ response, err := api.botRequest(ctx, "bots.info", values)
if err != nil {
return nil, err
}
diff --git a/vendor/github.com/nlopes/slack/channels.go b/vendor/github.com/nlopes/slack/channels.go
index 6204315a9..029337e4e 100644
--- a/vendor/github.com/nlopes/slack/channels.go
+++ b/vendor/github.com/nlopes/slack/channels.go
@@ -2,7 +2,6 @@ package slack
import (
"context"
- "errors"
"net/url"
"strconv"
)
@@ -19,25 +18,50 @@ type channelResponseFull struct {
// Channel contains information about the channel
type Channel struct {
- groupConversation
+ GroupConversation
IsChannel bool `json:"is_channel"`
IsGeneral bool `json:"is_general"`
IsMember bool `json:"is_member"`
Locale string `json:"locale"`
}
-func channelRequest(ctx context.Context, client HTTPRequester, path string, values url.Values, debug bool) (*channelResponseFull, error) {
+func (api *Client) channelRequest(ctx context.Context, path string, values url.Values) (*channelResponseFull, error) {
response := &channelResponseFull{}
- err := postForm(ctx, client, SLACK_API+path, values, response, debug)
+ err := postForm(ctx, api.httpclient, api.endpoint+path, values, response, api)
if err != nil {
return nil, err
}
- if !response.Ok {
- return nil, errors.New(response.Error)
+
+ if err := response.Err(); err != nil {
+ return nil, err
}
+
return response, nil
}
+type channelsConfig struct {
+ values url.Values
+}
+
+// GetChannelsOption option provided when getting channels.
+type GetChannelsOption func(*channelsConfig) error
+
+// GetChannelsOptionExcludeMembers excludes the members collection from each channel.
+func GetChannelsOptionExcludeMembers() GetChannelsOption {
+ return func(config *channelsConfig) error {
+ config.values.Add("exclude_members", "true")
+ return nil
+ }
+}
+
+// GetChannelsOptionExcludeArchived excludes archived channels from results.
+func GetChannelsOptionExcludeArchived() GetChannelsOption {
+ return func(config *channelsConfig) error {
+ config.values.Add("exclude_archived", "true")
+ return nil
+ }
+}
+
// ArchiveChannel archives the given channel
// see https://api.slack.com/methods/channels.archive
func (api *Client) ArchiveChannel(channelID string) error {
@@ -52,7 +76,7 @@ func (api *Client) ArchiveChannelContext(ctx context.Context, channelID string)
"channel": {channelID},
}
- _, err = channelRequest(ctx, api.httpclient, "channels.archive", values, api.debug)
+ _, err = api.channelRequest(ctx, "channels.archive", values)
return err
}
@@ -70,7 +94,7 @@ func (api *Client) UnarchiveChannelContext(ctx context.Context, channelID string
"channel": {channelID},
}
- _, err = channelRequest(ctx, api.httpclient, "channels.unarchive", values, api.debug)
+ _, err = api.channelRequest(ctx, "channels.unarchive", values)
return err
}
@@ -88,7 +112,7 @@ func (api *Client) CreateChannelContext(ctx context.Context, channelName string)
"name": {channelName},
}
- response, err := channelRequest(ctx, api.httpclient, "channels.create", values, api.debug)
+ response, err := api.channelRequest(ctx, "channels.create", values)
if err != nil {
return nil, err
}
@@ -133,7 +157,7 @@ func (api *Client) GetChannelHistoryContext(ctx context.Context, channelID strin
}
}
- response, err := channelRequest(ctx, api.httpclient, "channels.history", values, api.debug)
+ response, err := api.channelRequest(ctx, "channels.history", values)
if err != nil {
return nil, err
}
@@ -150,11 +174,12 @@ func (api *Client) GetChannelInfo(channelID string) (*Channel, error) {
// see https://api.slack.com/methods/channels.info
func (api *Client) GetChannelInfoContext(ctx context.Context, channelID string) (*Channel, error) {
values := url.Values{
- "token": {api.token},
- "channel": {channelID},
+ "token": {api.token},
+ "channel": {channelID},
+ "include_locale": {strconv.FormatBool(true)},
}
- response, err := channelRequest(ctx, api.httpclient, "channels.info", values, api.debug)
+ response, err := api.channelRequest(ctx, "channels.info", values)
if err != nil {
return nil, err
}
@@ -167,7 +192,7 @@ func (api *Client) InviteUserToChannel(channelID, user string) (*Channel, error)
return api.InviteUserToChannelContext(context.Background(), channelID, user)
}
-// InviteUserToChannelCustom invites a user to a given channel and returns a *Channel with a custom context
+// InviteUserToChannelContext invites a user to a given channel and returns a *Channel with a custom context
// see https://api.slack.com/methods/channels.invite
func (api *Client) InviteUserToChannelContext(ctx context.Context, channelID, user string) (*Channel, error) {
values := url.Values{
@@ -176,7 +201,7 @@ func (api *Client) InviteUserToChannelContext(ctx context.Context, channelID, us
"user": {user},
}
- response, err := channelRequest(ctx, api.httpclient, "channels.invite", values, api.debug)
+ response, err := api.channelRequest(ctx, "channels.invite", values)
if err != nil {
return nil, err
}
@@ -197,7 +222,7 @@ func (api *Client) JoinChannelContext(ctx context.Context, channelName string) (
"name": {channelName},
}
- response, err := channelRequest(ctx, api.httpclient, "channels.join", values, api.debug)
+ response, err := api.channelRequest(ctx, "channels.join", values)
if err != nil {
return nil, err
}
@@ -218,7 +243,7 @@ func (api *Client) LeaveChannelContext(ctx context.Context, channelID string) (b
"channel": {channelID},
}
- response, err := channelRequest(ctx, api.httpclient, "channels.leave", values, api.debug)
+ response, err := api.channelRequest(ctx, "channels.leave", values)
if err != nil {
return false, err
}
@@ -241,27 +266,35 @@ func (api *Client) KickUserFromChannelContext(ctx context.Context, channelID, us
"user": {user},
}
- _, err = channelRequest(ctx, api.httpclient, "channels.kick", values, api.debug)
+ _, err = api.channelRequest(ctx, "channels.kick", values)
return err
}
// GetChannels retrieves all the channels
// see https://api.slack.com/methods/channels.list
-func (api *Client) GetChannels(excludeArchived bool) ([]Channel, error) {
- return api.GetChannelsContext(context.Background(), excludeArchived)
+func (api *Client) GetChannels(excludeArchived bool, options ...GetChannelsOption) ([]Channel, error) {
+ return api.GetChannelsContext(context.Background(), excludeArchived, options...)
}
// GetChannelsContext retrieves all the channels with a custom context
// see https://api.slack.com/methods/channels.list
-func (api *Client) GetChannelsContext(ctx context.Context, excludeArchived bool) ([]Channel, error) {
- values := url.Values{
- "token": {api.token},
+func (api *Client) GetChannelsContext(ctx context.Context, excludeArchived bool, options ...GetChannelsOption) ([]Channel, error) {
+ config := channelsConfig{
+ values: url.Values{
+ "token": {api.token},
+ },
}
if excludeArchived {
- values.Add("exclude_archived", "1")
+ options = append(options, GetChannelsOptionExcludeArchived())
+ }
+
+ for _, opt := range options {
+ if err := opt(&config); err != nil {
+ return nil, err
+ }
}
- response, err := channelRequest(ctx, api.httpclient, "channels.list", values, api.debug)
+ response, err := api.channelRequest(ctx, "channels.list", config.values)
if err != nil {
return nil, err
}
@@ -288,7 +321,7 @@ func (api *Client) SetChannelReadMarkContext(ctx context.Context, channelID, ts
"ts": {ts},
}
- _, err = channelRequest(ctx, api.httpclient, "channels.mark", values, api.debug)
+ _, err = api.channelRequest(ctx, "channels.mark", values)
return err
}
@@ -309,7 +342,7 @@ func (api *Client) RenameChannelContext(ctx context.Context, channelID, name str
// XXX: the created entry in this call returns a string instead of a number
// so I may have to do some workaround to solve it.
- response, err := channelRequest(ctx, api.httpclient, "channels.rename", values, api.debug)
+ response, err := api.channelRequest(ctx, "channels.rename", values)
if err != nil {
return nil, err
}
@@ -331,7 +364,7 @@ func (api *Client) SetChannelPurposeContext(ctx context.Context, channelID, purp
"purpose": {purpose},
}
- response, err := channelRequest(ctx, api.httpclient, "channels.setPurpose", values, api.debug)
+ response, err := api.channelRequest(ctx, "channels.setPurpose", values)
if err != nil {
return "", err
}
@@ -353,7 +386,7 @@ func (api *Client) SetChannelTopicContext(ctx context.Context, channelID, topic
"topic": {topic},
}
- response, err := channelRequest(ctx, api.httpclient, "channels.setTopic", values, api.debug)
+ response, err := api.channelRequest(ctx, "channels.setTopic", values)
if err != nil {
return "", err
}
@@ -374,7 +407,7 @@ func (api *Client) GetChannelRepliesContext(ctx context.Context, channelID, thre
"channel": {channelID},
"thread_ts": {thread_ts},
}
- response, err := channelRequest(ctx, api.httpclient, "channels.replies", values, api.debug)
+ response, err := api.channelRequest(ctx, "channels.replies", values)
if err != nil {
return nil, err
}
diff --git a/vendor/github.com/nlopes/slack/chat.go b/vendor/github.com/nlopes/slack/chat.go
index 8cc6bdefd..25b5db36a 100644
--- a/vendor/github.com/nlopes/slack/chat.go
+++ b/vendor/github.com/nlopes/slack/chat.go
@@ -43,19 +43,18 @@ func (c chatResponseFull) getMessageTimestamp() string {
// PostMessageParameters contains all the parameters necessary (including the optional ones) for a PostMessage() request
type PostMessageParameters struct {
- Username string `json:"username"`
- AsUser bool `json:"as_user"`
- Parse string `json:"parse"`
- ThreadTimestamp string `json:"thread_ts"`
- ReplyBroadcast bool `json:"reply_broadcast"`
- LinkNames int `json:"link_names"`
- Attachments []Attachment `json:"attachments"`
- UnfurlLinks bool `json:"unfurl_links"`
- UnfurlMedia bool `json:"unfurl_media"`
- IconURL string `json:"icon_url"`
- IconEmoji string `json:"icon_emoji"`
- Markdown bool `json:"mrkdwn,omitempty"`
- EscapeText bool `json:"escape_text"`
+ Username string `json:"username"`
+ AsUser bool `json:"as_user"`
+ Parse string `json:"parse"`
+ ThreadTimestamp string `json:"thread_ts"`
+ ReplyBroadcast bool `json:"reply_broadcast"`
+ LinkNames int `json:"link_names"`
+ UnfurlLinks bool `json:"unfurl_links"`
+ UnfurlMedia bool `json:"unfurl_media"`
+ IconURL string `json:"icon_url"`
+ IconEmoji string `json:"icon_emoji"`
+ Markdown bool `json:"mrkdwn,omitempty"`
+ EscapeText bool `json:"escape_text"`
// chat.postEphemeral support
Channel string `json:"channel"`
@@ -71,7 +70,6 @@ func NewPostMessageParameters() PostMessageParameters {
Parse: DEFAULT_MESSAGE_PARSE,
ThreadTimestamp: DEFAULT_MESSAGE_THREAD_TIMESTAMP,
LinkNames: DEFAULT_MESSAGE_LINK_NAMES,
- Attachments: nil,
UnfurlLinks: DEFAULT_MESSAGE_UNFURL_LINKS,
UnfurlMedia: DEFAULT_MESSAGE_UNFURL_MEDIA,
IconURL: DEFAULT_MESSAGE_ICON_URL,
@@ -96,26 +94,24 @@ func (api *Client) DeleteMessageContext(ctx context.Context, channel, messageTim
// PostMessage sends a message to a channel.
// Message is escaped by default according to https://api.slack.com/docs/formatting
// Use http://davestevens.github.io/slack-message-builder/ to help crafting your message.
-func (api *Client) PostMessage(channel, text string, params PostMessageParameters) (string, string, error) {
+func (api *Client) PostMessage(channelID string, options ...MsgOption) (string, string, error) {
respChannel, respTimestamp, _, err := api.SendMessageContext(
context.Background(),
- channel,
- MsgOptionText(text, params.EscapeText),
- MsgOptionAttachments(params.Attachments...),
- MsgOptionPostMessageParameters(params),
+ channelID,
+ MsgOptionPost(),
+ MsgOptionCompose(options...),
)
return respChannel, respTimestamp, err
}
// PostMessageContext sends a message to a channel with a custom context
-// For more details, see PostMessage documentation
-func (api *Client) PostMessageContext(ctx context.Context, channel, text string, params PostMessageParameters) (string, string, error) {
+// For more details, see PostMessage documentation.
+func (api *Client) PostMessageContext(ctx context.Context, channelID string, options ...MsgOption) (string, string, error) {
respChannel, respTimestamp, _, err := api.SendMessageContext(
ctx,
- channel,
- MsgOptionText(text, params.EscapeText),
- MsgOptionAttachments(params.Attachments...),
- MsgOptionPostMessageParameters(params),
+ channelID,
+ MsgOptionPost(),
+ MsgOptionCompose(options...),
)
return respChannel, respTimestamp, err
}
@@ -135,18 +131,23 @@ func (api *Client) PostEphemeral(channelID, userID string, options ...MsgOption)
// PostEphemeralContext sends an ephemeal message to a user in a channel with a custom context
// For more details, see PostEphemeral documentation
func (api *Client) PostEphemeralContext(ctx context.Context, channelID, userID string, options ...MsgOption) (timestamp string, err error) {
- _, timestamp, _, err = api.SendMessageContext(ctx, channelID, append(options, MsgOptionPostEphemeral2(userID))...)
+ _, timestamp, _, err = api.SendMessageContext(ctx, channelID, MsgOptionPostEphemeral(userID), MsgOptionCompose(options...))
return timestamp, err
}
// UpdateMessage updates a message in a channel
-func (api *Client) UpdateMessage(channelID, timestamp, text string) (string, string, string, error) {
- return api.UpdateMessageContext(context.Background(), channelID, timestamp, text)
+func (api *Client) UpdateMessage(channelID, timestamp string, options ...MsgOption) (string, string, string, error) {
+ return api.SendMessageContext(context.Background(), channelID, MsgOptionUpdate(timestamp), MsgOptionCompose(options...))
}
// UpdateMessageContext updates a message in a channel
-func (api *Client) UpdateMessageContext(ctx context.Context, channelID, timestamp, text string) (string, string, string, error) {
- return api.SendMessageContext(ctx, channelID, MsgOptionUpdate(timestamp), MsgOptionText(text, true))
+func (api *Client) UpdateMessageContext(ctx context.Context, channelID, timestamp string, options ...MsgOption) (string, string, string, error) {
+ return api.SendMessageContext(ctx, channelID, MsgOptionUpdate(timestamp), MsgOptionCompose(options...))
+}
+
+// UnfurlMessage unfurls a message in a channel
+func (api *Client) UnfurlMessage(channelID, timestamp string, unfurls map[string]Attachment, options ...MsgOption) (string, string, string, error) {
+ return api.SendMessageContext(context.Background(), channelID, MsgOptionUnfurl(timestamp, unfurls), MsgOptionCompose(options...))
}
// SendMessage more flexible method for configuring messages.
@@ -161,11 +162,11 @@ func (api *Client) SendMessageContext(ctx context.Context, channelID string, opt
response chatResponseFull
)
- if config, err = applyMsgOptions(api.token, channelID, options...); err != nil {
+ if config, err = applyMsgOptions(api.token, channelID, api.endpoint, options...); err != nil {
return "", "", "", err
}
- if err = postForm(ctx, api.httpclient, config.endpoint, config.values, &response, api.debug); err != nil {
+ if err = postForm(ctx, api.httpclient, config.endpoint, config.values, &response, api); err != nil {
return "", "", "", err
}
@@ -175,14 +176,15 @@ func (api *Client) SendMessageContext(ctx context.Context, channelID string, opt
// UnsafeApplyMsgOptions utility function for debugging/testing chat requests.
// NOTE: USE AT YOUR OWN RISK: No issues relating to the use of this function
// will be supported by the library.
-func UnsafeApplyMsgOptions(token, channel string, options ...MsgOption) (string, url.Values, error) {
- config, err := applyMsgOptions(token, channel, options...)
+func UnsafeApplyMsgOptions(token, channel, apiurl string, options ...MsgOption) (string, url.Values, error) {
+ config, err := applyMsgOptions(token, channel, apiurl, options...)
return config.endpoint, config.values, err
}
-func applyMsgOptions(token, channel string, options ...MsgOption) (sendConfig, error) {
+func applyMsgOptions(token, channel, apiurl string, options ...MsgOption) (sendConfig, error) {
config := sendConfig{
- endpoint: SLACK_API + string(chatPostMessage),
+ apiurl: apiurl,
+ endpoint: apiurl + string(chatPostMessage),
values: url.Values{
"token": {token},
"channel": {channel},
@@ -206,9 +208,11 @@ const (
chatDelete sendMode = "chat.delete"
chatPostEphemeral sendMode = "chat.postEphemeral"
chatMeMessage sendMode = "chat.meMessage"
+ chatUnfurl sendMode = "chat.unfurl"
)
type sendConfig struct {
+ apiurl string
endpoint string
values url.Values
}
@@ -219,26 +223,16 @@ type MsgOption func(*sendConfig) error
// MsgOptionPost posts a messages, this is the default.
func MsgOptionPost() MsgOption {
return func(config *sendConfig) error {
- config.endpoint = SLACK_API + string(chatPostMessage)
+ config.endpoint = config.apiurl + string(chatPostMessage)
config.values.Del("ts")
return nil
}
}
-// MsgOptionPostEphemeral - DEPRECATED: use MsgOptionPostEphemeral2
-// posts an ephemeral message.
-func MsgOptionPostEphemeral() MsgOption {
+// MsgOptionPostEphemeral - posts an ephemeral message to the provided user.
+func MsgOptionPostEphemeral(userID string) MsgOption {
return func(config *sendConfig) error {
- config.endpoint = SLACK_API + string(chatPostEphemeral)
- config.values.Del("ts")
- return nil
- }
-}
-
-// MsgOptionPostEphemeral2 - posts an ephemeral message to the provided user.
-func MsgOptionPostEphemeral2(userID string) MsgOption {
- return func(config *sendConfig) error {
- config.endpoint = SLACK_API + string(chatPostEphemeral)
+ config.endpoint = config.apiurl + string(chatPostEphemeral)
MsgOptionUser(userID)(config)
config.values.Del("ts")
@@ -249,7 +243,7 @@ func MsgOptionPostEphemeral2(userID string) MsgOption {
// MsgOptionMeMessage posts a "me message" type from the calling user
func MsgOptionMeMessage() MsgOption {
return func(config *sendConfig) error {
- config.endpoint = SLACK_API + string(chatMeMessage)
+ config.endpoint = config.apiurl + string(chatMeMessage)
return nil
}
}
@@ -257,7 +251,7 @@ func MsgOptionMeMessage() MsgOption {
// MsgOptionUpdate updates a message based on the timestamp.
func MsgOptionUpdate(timestamp string) MsgOption {
return func(config *sendConfig) error {
- config.endpoint = SLACK_API + string(chatUpdate)
+ config.endpoint = config.apiurl + string(chatUpdate)
config.values.Add("ts", timestamp)
return nil
}
@@ -266,12 +260,25 @@ func MsgOptionUpdate(timestamp string) MsgOption {
// MsgOptionDelete deletes a message based on the timestamp.
func MsgOptionDelete(timestamp string) MsgOption {
return func(config *sendConfig) error {
- config.endpoint = SLACK_API + string(chatDelete)
+ config.endpoint = config.apiurl + string(chatDelete)
config.values.Add("ts", timestamp)
return nil
}
}
+// MsgOptionUnfurl unfurls a message based on the timestamp.
+func MsgOptionUnfurl(timestamp string, unfurls map[string]Attachment) MsgOption {
+ return func(config *sendConfig) error {
+ config.endpoint = config.apiurl + string(chatUnfurl)
+ config.values.Add("ts", timestamp)
+ unfurlsStr, err := json.Marshal(unfurls)
+ if err == nil {
+ config.values.Add("unfurls", string(unfurlsStr))
+ }
+ return err
+ }
+}
+
// MsgOptionAsUser whether or not to send the message as the user.
func MsgOptionAsUser(b bool) MsgOption {
return func(config *sendConfig) error {
@@ -290,6 +297,14 @@ func MsgOptionUser(userID string) MsgOption {
}
}
+// MsgOptionUsername set the username for the message.
+func MsgOptionUsername(username string) MsgOption {
+ return func(config *sendConfig) error {
+ config.values.Set("username", username)
+ return nil
+ }
+}
+
// MsgOptionText provide the text for the message, optionally escape the provided
// text.
func MsgOptionText(text string, escape bool) MsgOption {
@@ -317,6 +332,21 @@ func MsgOptionAttachments(attachments ...Attachment) MsgOption {
}
}
+// MsgOptionBlocks sets blocks for the message
+func MsgOptionBlocks(blocks ...Block) MsgOption {
+ return func(config *sendConfig) error {
+ if blocks == nil {
+ return nil
+ }
+
+ blocks, err := json.Marshal(blocks)
+ if err == nil {
+ config.values.Set("blocks", string(blocks))
+ }
+ return err
+ }
+}
+
// MsgOptionEnableLinkUnfurl enables link unfurling
func MsgOptionEnableLinkUnfurl() MsgOption {
return func(config *sendConfig) error {
@@ -365,7 +395,7 @@ func MsgOptionBroadcast() MsgOption {
}
}
-// this function combines multiple options into a single option.
+// MsgOptionCompose combines multiple options into a single option.
func MsgOptionCompose(options ...MsgOption) MsgOption {
return func(c *sendConfig) error {
for _, opt := range options {
@@ -377,19 +407,36 @@ func MsgOptionCompose(options ...MsgOption) MsgOption {
}
}
+// MsgOptionParse set parse option.
func MsgOptionParse(b bool) MsgOption {
return func(c *sendConfig) error {
var v string
if b {
- v = "1"
+ v = "full"
} else {
- v = "0"
+ v = "none"
}
c.values.Set("parse", v)
return nil
}
}
+// MsgOptionIconURL sets an icon URL
+func MsgOptionIconURL(iconURL string) MsgOption {
+ return func(c *sendConfig) error {
+ c.values.Set("icon_url", iconURL)
+ return nil
+ }
+}
+
+// MsgOptionIconEmoji sets an icon emoji
+func MsgOptionIconEmoji(iconEmoji string) MsgOption {
+ return func(c *sendConfig) error {
+ c.values.Set("icon_emoji", iconEmoji)
+ return nil
+ }
+}
+
// UnsafeMsgOptionEndpoint deliver the message to the specified endpoint.
// NOTE: USE AT YOUR OWN RISK: No issues relating to the use of this Option
// will be supported by the library, it is subject to change without notice that
@@ -456,3 +503,38 @@ func MsgOptionPostMessageParameters(params PostMessageParameters) MsgOption {
return nil
}
}
+
+// PermalinkParameters are the parameters required to get a permalink to a
+// message. Slack documentation can be found here:
+// https://api.slack.com/methods/chat.getPermalink
+type PermalinkParameters struct {
+ Channel string
+ Ts string
+}
+
+// GetPermalink returns the permalink for a message. It takes
+// PermalinkParameters and returns a string containing the permalink. It
+// returns an error if unable to retrieve the permalink.
+func (api *Client) GetPermalink(params *PermalinkParameters) (string, error) {
+ return api.GetPermalinkContext(context.Background(), params)
+}
+
+// GetPermalinkContext returns the permalink for a message using a custom context.
+func (api *Client) GetPermalinkContext(ctx context.Context, params *PermalinkParameters) (string, error) {
+ values := url.Values{
+ "token": {api.token},
+ "channel": {params.Channel},
+ "message_ts": {params.Ts},
+ }
+
+ response := struct {
+ Channel string `json:"channel"`
+ Permalink string `json:"permalink"`
+ SlackResponse
+ }{}
+ err := api.getMethod(ctx, "chat.getPermalink", values, &response)
+ if err != nil {
+ return "", err
+ }
+ return response.Permalink, response.Err()
+}
diff --git a/vendor/github.com/nlopes/slack/conversation.go b/vendor/github.com/nlopes/slack/conversation.go
index 1c64116ef..47a54c54a 100644
--- a/vendor/github.com/nlopes/slack/conversation.go
+++ b/vendor/github.com/nlopes/slack/conversation.go
@@ -2,14 +2,13 @@ package slack
import (
"context"
- "errors"
"net/url"
"strconv"
"strings"
)
// Conversation is the foundation for IM and BaseGroupConversation
-type conversation struct {
+type Conversation struct {
ID string `json:"id"`
Created JSONTime `json:"created"`
IsOpen bool `json:"is_open"`
@@ -36,8 +35,8 @@ type conversation struct {
}
// GroupConversation is the foundation for Group and Channel
-type groupConversation struct {
- conversation
+type GroupConversation struct {
+ Conversation
Name string `json:"name"`
Creator string `json:"creator"`
IsArchived bool `json:"is_archived"`
@@ -67,10 +66,11 @@ type GetUsersInConversationParameters struct {
}
type GetConversationsForUserParameters struct {
- UserID string
- Cursor string
- Types []string
- Limit int
+ UserID string
+ Cursor string
+ Types []string
+ Limit int
+ ExcludeArchived bool
}
type responseMetaData struct {
@@ -99,13 +99,15 @@ func (api *Client) GetUsersInConversationContext(ctx context.Context, params *Ge
ResponseMetaData responseMetaData `json:"response_metadata"`
SlackResponse
}{}
- err := postSlackMethod(ctx, api.httpclient, "conversations.members", values, &response, api.debug)
+ err := api.postMethod(ctx, "conversations.members", values, &response)
if err != nil {
return nil, "", err
}
- if !response.Ok {
- return nil, "", errors.New(response.Error)
+
+ if err := response.Err(); err != nil {
+ return nil, "", err
}
+
return response.Members, response.ResponseMetaData.NextCursor, nil
}
@@ -118,7 +120,9 @@ func (api *Client) GetConversationsForUser(params *GetConversationsForUserParame
func (api *Client) GetConversationsForUserContext(ctx context.Context, params *GetConversationsForUserParameters) (channels []Channel, nextCursor string, err error) {
values := url.Values{
"token": {api.token},
- "user": {params.UserID},
+ }
+ if params.UserID != "" {
+ values.Add("user", params.UserID)
}
if params.Cursor != "" {
values.Add("cursor", params.Cursor)
@@ -129,19 +133,20 @@ func (api *Client) GetConversationsForUserContext(ctx context.Context, params *G
if params.Types != nil {
values.Add("types", strings.Join(params.Types, ","))
}
+ if params.ExcludeArchived {
+ values.Add("exclude_archived", "true")
+ }
response := struct {
Channels []Channel `json:"channels"`
ResponseMetaData responseMetaData `json:"response_metadata"`
SlackResponse
}{}
- err = postSlackMethod(ctx, api.httpclient, "users.conversations", values, &response, api.debug)
+ err = api.postMethod(ctx, "users.conversations", values, &response)
if err != nil {
return nil, "", err
}
- if !response.Ok {
- return nil, "", errors.New(response.Error)
- }
- return response.Channels, response.ResponseMetaData.NextCursor, nil
+
+ return response.Channels, response.ResponseMetaData.NextCursor, response.Err()
}
// ArchiveConversation archives a conversation
@@ -156,7 +161,7 @@ func (api *Client) ArchiveConversationContext(ctx context.Context, channelID str
"channel": {channelID},
}
response := SlackResponse{}
- err := postSlackMethod(ctx, api.httpclient, "conversations.archive", values, &response, api.debug)
+ err := api.postMethod(ctx, "conversations.archive", values, &response)
if err != nil {
return err
}
@@ -176,7 +181,7 @@ func (api *Client) UnArchiveConversationContext(ctx context.Context, channelID s
"channel": {channelID},
}
response := SlackResponse{}
- err := postSlackMethod(ctx, api.httpclient, "conversations.unarchive", values, &response, api.debug)
+ err := api.postMethod(ctx, "conversations.unarchive", values, &response)
if err != nil {
return err
}
@@ -200,7 +205,7 @@ func (api *Client) SetTopicOfConversationContext(ctx context.Context, channelID,
SlackResponse
Channel *Channel `json:"channel"`
}{}
- err := postSlackMethod(ctx, api.httpclient, "conversations.setTopic", values, &response, api.debug)
+ err := api.postMethod(ctx, "conversations.setTopic", values, &response)
if err != nil {
return nil, err
}
@@ -224,7 +229,7 @@ func (api *Client) SetPurposeOfConversationContext(ctx context.Context, channelI
SlackResponse
Channel *Channel `json:"channel"`
}{}
- err := postSlackMethod(ctx, api.httpclient, "conversations.setPurpose", values, &response, api.debug)
+ err := api.postMethod(ctx, "conversations.setPurpose", values, &response)
if err != nil {
return nil, err
}
@@ -248,7 +253,7 @@ func (api *Client) RenameConversationContext(ctx context.Context, channelID, cha
SlackResponse
Channel *Channel `json:"channel"`
}{}
- err := postSlackMethod(ctx, api.httpclient, "conversations.rename", values, &response, api.debug)
+ err := api.postMethod(ctx, "conversations.rename", values, &response)
if err != nil {
return nil, err
}
@@ -272,7 +277,7 @@ func (api *Client) InviteUsersToConversationContext(ctx context.Context, channel
SlackResponse
Channel *Channel `json:"channel"`
}{}
- err := postSlackMethod(ctx, api.httpclient, "conversations.invite", values, &response, api.debug)
+ err := api.postMethod(ctx, "conversations.invite", values, &response)
if err != nil {
return nil, err
}
@@ -293,7 +298,7 @@ func (api *Client) KickUserFromConversationContext(ctx context.Context, channelI
"user": {user},
}
response := SlackResponse{}
- err := postSlackMethod(ctx, api.httpclient, "conversations.kick", values, &response, api.debug)
+ err := api.postMethod(ctx, "conversations.kick", values, &response)
if err != nil {
return err
}
@@ -318,7 +323,7 @@ func (api *Client) CloseConversationContext(ctx context.Context, channelID strin
AlreadyClosed bool `json:"already_closed"`
}{}
- err = postSlackMethod(ctx, api.httpclient, "conversations.close", values, &response, api.debug)
+ err = api.postMethod(ctx, "conversations.close", values, &response)
if err != nil {
return false, false, err
}
@@ -338,13 +343,12 @@ func (api *Client) CreateConversationContext(ctx context.Context, channelName st
"name": {channelName},
"is_private": {strconv.FormatBool(isPrivate)},
}
- response, err := channelRequest(
- ctx, api.httpclient, "conversations.create", values, api.debug)
+ response, err := api.channelRequest(ctx, "conversations.create", values)
if err != nil {
return nil, err
}
- return &response.Channel, response.Err()
+ return &response.Channel, nil
}
// GetConversationInfo retrieves information about a conversation
@@ -359,8 +363,7 @@ func (api *Client) GetConversationInfoContext(ctx context.Context, channelID str
"channel": {channelID},
"include_locale": {strconv.FormatBool(includeLocale)},
}
- response, err := channelRequest(
- ctx, api.httpclient, "conversations.info", values, api.debug)
+ response, err := api.channelRequest(ctx, "conversations.info", values)
if err != nil {
return nil, err
}
@@ -380,7 +383,7 @@ func (api *Client) LeaveConversationContext(ctx context.Context, channelID strin
"channel": {channelID},
}
- response, err := channelRequest(ctx, api.httpclient, "conversations.leave", values, api.debug)
+ response, err := api.channelRequest(ctx, "conversations.leave", values)
if err != nil {
return false, err
}
@@ -436,7 +439,7 @@ func (api *Client) GetConversationRepliesContext(ctx context.Context, params *Ge
Messages []Message `json:"messages"`
}{}
- err = postSlackMethod(ctx, api.httpclient, "conversations.replies", values, &response, api.debug)
+ err = api.postMethod(ctx, "conversations.replies", values, &response)
if err != nil {
return nil, false, "", err
}
@@ -476,7 +479,7 @@ func (api *Client) GetConversationsContext(ctx context.Context, params *GetConve
ResponseMetaData responseMetaData `json:"response_metadata"`
SlackResponse
}{}
- err = postSlackMethod(ctx, api.httpclient, "conversations.list", values, &response, api.debug)
+ err = api.postMethod(ctx, "conversations.list", values, &response)
if err != nil {
return nil, "", err
}
@@ -513,7 +516,7 @@ func (api *Client) OpenConversationContext(ctx context.Context, params *OpenConv
AlreadyOpen bool `json:"already_open"`
SlackResponse
}{}
- err := postSlackMethod(ctx, api.httpclient, "conversations.open", values, &response, api.debug)
+ err := api.postMethod(ctx, "conversations.open", values, &response)
if err != nil {
return nil, false, false, err
}
@@ -537,7 +540,7 @@ func (api *Client) JoinConversationContext(ctx context.Context, channelID string
} `json:"response_metadata"`
SlackResponse
}{}
- err := postSlackMethod(ctx, api.httpclient, "conversations.join", values, &response, api.debug)
+ err := api.postMethod(ctx, "conversations.join", values, &response)
if err != nil {
return nil, "", nil, err
}
@@ -599,12 +602,10 @@ func (api *Client) GetConversationHistoryContext(ctx context.Context, params *Ge
response := GetConversationHistoryResponse{}
- err := postSlackMethod(ctx, api.httpclient, "conversations.history", values, &response, api.debug)
+ err := api.postMethod(ctx, "conversations.history", values, &response)
if err != nil {
return nil, err
}
- if !response.Ok {
- return nil, errors.New(response.Error)
- }
- return &response, nil
+
+ return &response, response.Err()
}
diff --git a/vendor/github.com/nlopes/slack/dialog.go b/vendor/github.com/nlopes/slack/dialog.go
index d1435d54c..376cd9e60 100644
--- a/vendor/github.com/nlopes/slack/dialog.go
+++ b/vendor/github.com/nlopes/slack/dialog.go
@@ -3,7 +3,7 @@ package slack
import (
"context"
"encoding/json"
- "errors"
+ "strings"
)
// InputType is the type of the dialog input type
@@ -14,7 +14,7 @@ const (
InputTypeText InputType = "text"
// InputTypeTextArea textarea input
InputTypeTextArea InputType = "textarea"
- // InputTypeSelect textfield input
+ // InputTypeSelect select menus input
InputTypeSelect InputType = "select"
)
@@ -25,6 +25,7 @@ type DialogInput struct {
Name string `json:"name"`
Placeholder string `json:"placeholder"`
Optional bool `json:"optional"`
+ Hint string `json:"hint"`
}
// DialogTrigger ...
@@ -36,8 +37,9 @@ type DialogTrigger struct {
// Dialog as in Slack dialogs
// https://api.slack.com/dialogs#option_element_attributes#top-level_dialog_attributes
type Dialog struct {
- TriggerID string `json:"trigger_id"` //Required
- CallbackID string `json:"callback_id"` //Required
+ TriggerID string `json:"trigger_id"` // Required
+ CallbackID string `json:"callback_id"` // Required
+ State string `json:"state,omitempty"` // Optional
Title string `json:"title"`
SubmitLabel string `json:"submit_label,omitempty"`
NotifyOnCancel bool `json:"notify_on_cancel"`
@@ -47,30 +49,13 @@ type Dialog struct {
// DialogElement abstract type for dialogs.
type DialogElement interface{}
-// DialogCallback is sent from Slack when a user submits a form from within a dialog
-type DialogCallback struct {
- Type string `json:"type"`
- CallbackID string `json:"callback_id"`
- Team Team `json:"team"`
- Channel Channel `json:"channel"`
- User User `json:"user"`
- ActionTs string `json:"action_ts"`
- Token string `json:"token"`
- ResponseURL string `json:"response_url"`
- Submission map[string]string `json:"submission"`
-}
+// DialogCallback DEPRECATED use InteractionCallback
+type DialogCallback InteractionCallback
-// DialogSuggestionCallback is sent from Slack when a user types in a select field with an external data source
-type DialogSuggestionCallback struct {
- Type string `json:"type"`
- Token string `json:"token"`
- ActionTs string `json:"action_ts"`
- Team Team `json:"team"`
- User User `json:"user"`
- Channel Channel `json:"channel"`
- ElementName string `json:"name"`
- Value string `json:"value"`
- CallbackID string `json:"callback_id"`
+// DialogSubmissionCallback is sent from Slack when a user submits a form from within a dialog
+type DialogSubmissionCallback struct {
+ State string `json:"state,omitempty"`
+ Submission map[string]string `json:"submission"`
}
// DialogOpenResponse response from `dialog.open`
@@ -84,6 +69,17 @@ type DialogResponseMetadata struct {
Messages []string `json:"messages"`
}
+// DialogInputValidationError is an error when user inputs incorrect value to form from within a dialog
+type DialogInputValidationError struct {
+ Name string `json:"name"`
+ Error string `json:"error"`
+}
+
+// DialogInputValidationErrors lists the name of field and that error messages
+type DialogInputValidationErrors struct {
+ Errors []DialogInputValidationError `json:"errors"`
+}
+
// OpenDialog opens a dialog window where the triggerID originated from.
// EXPERIMENTAL: dialog functionality is currently experimental, api is not considered stable.
func (api *Client) OpenDialog(triggerID string, dialog Dialog) (err error) {
@@ -94,7 +90,7 @@ func (api *Client) OpenDialog(triggerID string, dialog Dialog) (err error) {
// EXPERIMENTAL: dialog functionality is currently experimental, api is not considered stable.
func (api *Client) OpenDialogContext(ctx context.Context, triggerID string, dialog Dialog) (err error) {
if triggerID == "" {
- return errors.New("received empty parameters")
+ return ErrParametersMissing
}
req := DialogTrigger{
@@ -108,10 +104,15 @@ func (api *Client) OpenDialogContext(ctx context.Context, triggerID string, dial
}
response := &DialogOpenResponse{}
- endpoint := SLACK_API + "dialog.open"
- if err := postJSON(ctx, api.httpclient, endpoint, api.token, encoded, response, api.debug); err != nil {
+ endpoint := api.endpoint + "dialog.open"
+ if err := postJSON(ctx, api.httpclient, endpoint, api.token, encoded, response, api); err != nil {
return err
}
+ if len(response.DialogResponseMetadata.Messages) > 0 {
+ response.Ok = false
+ response.Error += "\n" + strings.Join(response.DialogResponseMetadata.Messages, "\n")
+ }
+
return response.Err()
}
diff --git a/vendor/github.com/nlopes/slack/dialog_select.go b/vendor/github.com/nlopes/slack/dialog_select.go
index cff35479a..975e6e1f2 100644
--- a/vendor/github.com/nlopes/slack/dialog_select.go
+++ b/vendor/github.com/nlopes/slack/dialog_select.go
@@ -24,6 +24,8 @@ type DialogInputSelect struct {
SelectedOptions string `json:"selected_options,omitempty"` //Optional. Default value for "external" only
Options []DialogSelectOption `json:"options,omitempty"` //One of options or option_groups is required.
OptionGroups []DialogOptionGroup `json:"option_groups,omitempty"` //Provide up to 100 options.
+ MinQueryLength int `json:"min_query_length,omitempty"` //Optional. minimum characters before query is sent.
+ Hint string `json:"hint,omitempty"` //Optional. Additional hint text.
}
// DialogSelectOption is an option for the user to select from the menu
@@ -53,14 +55,7 @@ func NewStaticSelectDialogInput(name, label string, options []DialogSelectOption
}
// NewGroupedSelectDialogInput creates grouped options select input for Dialogs.
-func NewGroupedSelectDialogInput(name, label string, groups map[string]map[string]string) *DialogInputSelect {
- optionGroups := []DialogOptionGroup{}
- for groupName, options := range groups {
- optionGroups = append(optionGroups, DialogOptionGroup{
- Label: groupName,
- Options: optionsFromMap(options),
- })
- }
+func NewGroupedSelectDialogInput(name, label string, options []DialogOptionGroup) *DialogInputSelect {
return &DialogInputSelect{
DialogInput: DialogInput{
Type: InputTypeSelect,
@@ -68,34 +63,15 @@ func NewGroupedSelectDialogInput(name, label string, groups map[string]map[strin
Label: label,
},
DataSource: DialogDataSourceStatic,
- OptionGroups: optionGroups,
- }
-}
-
-func optionsFromArray(options []string) []DialogSelectOption {
- selectOptions := make([]DialogSelectOption, len(options))
- for idx, value := range options {
- selectOptions[idx] = DialogSelectOption{
- Label: value,
- Value: value,
- }
- }
- return selectOptions
+ OptionGroups: options}
}
-func optionsFromMap(options map[string]string) []DialogSelectOption {
- selectOptions := make([]DialogSelectOption, len(options))
- idx := 0
- var option DialogSelectOption
- for key, value := range options {
- option = DialogSelectOption{
- Label: key,
- Value: value,
- }
- selectOptions[idx] = option
- idx++
+// NewDialogOptionGroup creates a DialogOptionGroup from several select options
+func NewDialogOptionGroup(label string, options ...DialogSelectOption) DialogOptionGroup {
+ return DialogOptionGroup{
+ Label: label,
+ Options: options,
}
- return selectOptions
}
// NewConversationsSelect returns a `Conversations` select
diff --git a/vendor/github.com/nlopes/slack/dnd.go b/vendor/github.com/nlopes/slack/dnd.go
index 26d36d6ae..a3aa680cd 100644
--- a/vendor/github.com/nlopes/slack/dnd.go
+++ b/vendor/github.com/nlopes/slack/dnd.go
@@ -2,7 +2,6 @@ package slack
import (
"context"
- "errors"
"net/url"
"strconv"
"strings"
@@ -36,16 +35,14 @@ type dndTeamInfoResponse struct {
SlackResponse
}
-func dndRequest(ctx context.Context, client HTTPRequester, path string, values url.Values, debug bool) (*dndResponseFull, error) {
+func (api *Client) dndRequest(ctx context.Context, path string, values url.Values) (*dndResponseFull, error) {
response := &dndResponseFull{}
- err := postSlackMethod(ctx, client, path, values, response, debug)
+ err := api.postMethod(ctx, path, values, response)
if err != nil {
return nil, err
}
- if !response.Ok {
- return nil, errors.New(response.Error)
- }
- return response, nil
+
+ return response, response.Err()
}
// EndDND ends the user's scheduled Do Not Disturb session
@@ -61,7 +58,7 @@ func (api *Client) EndDNDContext(ctx context.Context) error {
response := &SlackResponse{}
- if err := postSlackMethod(ctx, api.httpclient, "dnd.endDnd", values, response, api.debug); err != nil {
+ if err := api.postMethod(ctx, "dnd.endDnd", values, response); err != nil {
return err
}
@@ -79,7 +76,7 @@ func (api *Client) EndSnoozeContext(ctx context.Context) (*DNDStatus, error) {
"token": {api.token},
}
- response, err := dndRequest(ctx, api.httpclient, "dnd.endSnooze", values, api.debug)
+ response, err := api.dndRequest(ctx, "dnd.endSnooze", values)
if err != nil {
return nil, err
}
@@ -100,7 +97,7 @@ func (api *Client) GetDNDInfoContext(ctx context.Context, user *string) (*DNDSta
values.Set("user", *user)
}
- response, err := dndRequest(ctx, api.httpclient, "dnd.info", values, api.debug)
+ response, err := api.dndRequest(ctx, "dnd.info", values)
if err != nil {
return nil, err
}
@@ -120,12 +117,14 @@ func (api *Client) GetDNDTeamInfoContext(ctx context.Context, users []string) (m
}
response := &dndTeamInfoResponse{}
- if err := postSlackMethod(ctx, api.httpclient, "dnd.teamInfo", values, response, api.debug); err != nil {
+ if err := api.postMethod(ctx, "dnd.teamInfo", values, response); err != nil {
return nil, err
}
- if !response.Ok {
- return nil, errors.New(response.Error)
+
+ if response.Err() != nil {
+ return nil, response.Err()
}
+
return response.Users, nil
}
@@ -136,7 +135,7 @@ func (api *Client) SetSnooze(minutes int) (*DNDStatus, error) {
return api.SetSnoozeContext(context.Background(), minutes)
}
-// SetSnooze adjusts the snooze duration for a user's Do Not Disturb settings with a custom context.
+// SetSnoozeContext adjusts the snooze duration for a user's Do Not Disturb settings with a custom context.
// For more information see the SetSnooze docs
func (api *Client) SetSnoozeContext(ctx context.Context, minutes int) (*DNDStatus, error) {
values := url.Values{
@@ -144,7 +143,7 @@ func (api *Client) SetSnoozeContext(ctx context.Context, minutes int) (*DNDStatu
"num_minutes": {strconv.Itoa(minutes)},
}
- response, err := dndRequest(ctx, api.httpclient, "dnd.setSnooze", values, api.debug)
+ response, err := api.dndRequest(ctx, "dnd.setSnooze", values)
if err != nil {
return nil, err
}
diff --git a/vendor/github.com/nlopes/slack/emoji.go b/vendor/github.com/nlopes/slack/emoji.go
index fe2945c49..b2b0c6c90 100644
--- a/vendor/github.com/nlopes/slack/emoji.go
+++ b/vendor/github.com/nlopes/slack/emoji.go
@@ -2,7 +2,6 @@ package slack
import (
"context"
- "errors"
"net/url"
)
@@ -23,12 +22,14 @@ func (api *Client) GetEmojiContext(ctx context.Context) (map[string]string, erro
}
response := &emojiResponseFull{}
- err := postSlackMethod(ctx, api.httpclient, "emoji.list", values, response, api.debug)
+ err := api.postMethod(ctx, "emoji.list", values, response)
if err != nil {
return nil, err
}
- if !response.Ok {
- return nil, errors.New(response.Error)
+
+ if response.Err() != nil {
+ return nil, response.Err()
}
+
return response.Emoji, nil
}
diff --git a/vendor/github.com/nlopes/slack/errors.go b/vendor/github.com/nlopes/slack/errors.go
new file mode 100644
index 000000000..09113ff1c
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/errors.go
@@ -0,0 +1,18 @@
+package slack
+
+import "github.com/nlopes/slack/internal/errorsx"
+
+// Errors returned by various methods.
+const (
+ ErrAlreadyDisconnected = errorsx.String("Invalid call to Disconnect - Slack API is already disconnected")
+ ErrRTMDisconnected = errorsx.String("disconnect received while trying to connect")
+ ErrParametersMissing = errorsx.String("received empty parameters")
+ ErrInvalidConfiguration = errorsx.String("invalid configuration")
+ ErrMissingHeaders = errorsx.String("missing headers")
+ ErrExpiredTimestamp = errorsx.String("timestamp is too old")
+)
+
+// internal errors
+const (
+ errPaginationComplete = errorsx.String("pagination complete")
+)
diff --git a/vendor/github.com/nlopes/slack/files.go b/vendor/github.com/nlopes/slack/files.go
index 0550c9fb5..d1c4b9dff 100644
--- a/vendor/github.com/nlopes/slack/files.go
+++ b/vendor/github.com/nlopes/slack/files.go
@@ -2,7 +2,7 @@ package slack
import (
"context"
- "errors"
+ "fmt"
"io"
"net/url"
"strconv"
@@ -86,12 +86,30 @@ type File struct {
CommentsCount int `json:"comments_count"`
NumStars int `json:"num_stars"`
IsStarred bool `json:"is_starred"`
+ Shares Share `json:"shares"`
+}
+
+type Share struct {
+ Public map[string][]ShareFileInfo `json:"public"`
+}
+
+type ShareFileInfo struct {
+ ReplyUsers []string `json:"reply_users"`
+ ReplyUsersCount int `json:"reply_users_count"`
+ ReplyCount int `json:"reply_count"`
+ Ts string `json:"ts"`
+ ThreadTs string `json:"thread_ts"`
+ LatestReply string `json:"latest_reply"`
+ ChannelName string `json:"channel_name"`
+ TeamID string `json:"team_id"`
}
// FileUploadParameters contains all the parameters necessary (including the optional ones) for an UploadFile() request.
//
// There are three ways to upload a file. You can either set Content if file is small, set Reader if file is large,
// or provide a local file path in File to upload it from your filesystem.
+//
+// Note that when using the Reader option, you *must* specify the Filename, otherwise the Slack API isn't happy.
type FileUploadParameters struct {
File string
Content string
@@ -115,11 +133,21 @@ type GetFilesParameters struct {
Page int
}
+// ListFilesParameters contains all the parameters necessary (including the optional ones) for a ListFiles() request
+type ListFilesParameters struct {
+ Limit int
+ User string
+ Channel string
+ Types string
+ Cursor string
+}
+
type fileResponseFull struct {
File `json:"file"`
Paging `json:"paging"`
- Comments []Comment `json:"comments"`
- Files []File `json:"files"`
+ Comments []Comment `json:"comments"`
+ Files []File `json:"files"`
+ Metadata ResponseMetadata `json:"response_metadata"`
SlackResponse
}
@@ -137,16 +165,14 @@ func NewGetFilesParameters() GetFilesParameters {
}
}
-func fileRequest(ctx context.Context, client HTTPRequester, path string, values url.Values, debug bool) (*fileResponseFull, error) {
+func (api *Client) fileRequest(ctx context.Context, path string, values url.Values) (*fileResponseFull, error) {
response := &fileResponseFull{}
- err := postForm(ctx, client, SLACK_API+path, values, response, debug)
+ err := api.postMethod(ctx, path, values, response)
if err != nil {
return nil, err
}
- if !response.Ok {
- return nil, errors.New(response.Error)
- }
- return response, nil
+
+ return response, response.Err()
}
// GetFileInfo retrieves a file and related comments
@@ -163,18 +189,57 @@ func (api *Client) GetFileInfoContext(ctx context.Context, fileID string, count,
"page": {strconv.Itoa(page)},
}
- response, err := fileRequest(ctx, api.httpclient, "files.info", values, api.debug)
+ response, err := api.fileRequest(ctx, "files.info", values)
if err != nil {
return nil, nil, nil, err
}
return &response.File, response.Comments, &response.Paging, nil
}
+// GetFile retreives a given file from its private download URL
+func (api *Client) GetFile(downloadURL string, writer io.Writer) error {
+ return downloadFile(api.httpclient, api.token, downloadURL, writer, api)
+}
+
// GetFiles retrieves all files according to the parameters given
func (api *Client) GetFiles(params GetFilesParameters) ([]File, *Paging, error) {
return api.GetFilesContext(context.Background(), params)
}
+// ListFiles retrieves all files according to the parameters given. Uses cursor based pagination.
+func (api *Client) ListFiles(params ListFilesParameters) ([]File, *ListFilesParameters, error) {
+ return api.ListFilesContext(context.Background(), params)
+}
+
+// ListFilesContext retrieves all files according to the parameters given with a custom context. Uses cursor based pagination.
+func (api *Client) ListFilesContext(ctx context.Context, params ListFilesParameters) ([]File, *ListFilesParameters, error) {
+ values := url.Values{
+ "token": {api.token},
+ }
+
+ if params.User != DEFAULT_FILES_USER {
+ values.Add("user", params.User)
+ }
+ if params.Channel != DEFAULT_FILES_CHANNEL {
+ values.Add("channel", params.Channel)
+ }
+ if params.Limit != DEFAULT_FILES_COUNT {
+ values.Add("limit", strconv.Itoa(params.Limit))
+ }
+ if params.Cursor != "" {
+ values.Add("cursor", params.Cursor)
+ }
+
+ response, err := api.fileRequest(ctx, "files.list", values)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ params.Cursor = response.Metadata.Cursor
+
+ return response.Files, ¶ms, nil
+}
+
// GetFilesContext retrieves all files according to the parameters given with a custom context
func (api *Client) GetFilesContext(ctx context.Context, params GetFilesParameters) ([]File, *Paging, error) {
values := url.Values{
@@ -202,7 +267,7 @@ func (api *Client) GetFilesContext(ctx context.Context, params GetFilesParameter
values.Add("page", strconv.Itoa(params.Page))
}
- response, err := fileRequest(ctx, api.httpclient, "files.list", values, api.debug)
+ response, err := api.fileRequest(ctx, "files.list", values)
if err != nil {
return nil, nil, err
}
@@ -222,6 +287,9 @@ func (api *Client) UploadFileContext(ctx context.Context, params FileUploadParam
if err != nil {
return nil, err
}
+ if params.Filename == "" {
+ return nil, fmt.Errorf("files.upload: FileUploadParameters.Filename is mandatory")
+ }
response := &fileResponseFull{}
values := url.Values{
"token": {api.token},
@@ -246,19 +314,17 @@ func (api *Client) UploadFileContext(ctx context.Context, params FileUploadParam
}
if params.Content != "" {
values.Add("content", params.Content)
- err = postForm(ctx, api.httpclient, SLACK_API+"files.upload", values, response, api.debug)
+ err = api.postMethod(ctx, "files.upload", values, response)
} else if params.File != "" {
- err = postLocalWithMultipartResponse(ctx, api.httpclient, "files.upload", params.File, "file", values, response, api.debug)
+ err = postLocalWithMultipartResponse(ctx, api.httpclient, api.endpoint+"files.upload", params.File, "file", values, response, api)
} else if params.Reader != nil {
- err = postWithMultipartResponse(ctx, api.httpclient, "files.upload", params.Filename, "file", values, params.Reader, response, api.debug)
+ err = postWithMultipartResponse(ctx, api.httpclient, api.endpoint+"files.upload", params.Filename, "file", values, params.Reader, response, api)
}
if err != nil {
return nil, err
}
- if !response.Ok {
- return nil, errors.New(response.Error)
- }
- return &response.File, nil
+
+ return &response.File, response.Err()
}
// DeleteFileComment deletes a file's comment
@@ -269,7 +335,7 @@ func (api *Client) DeleteFileComment(commentID, fileID string) error {
// DeleteFileCommentContext deletes a file's comment with a custom context
func (api *Client) DeleteFileCommentContext(ctx context.Context, fileID, commentID string) (err error) {
if fileID == "" || commentID == "" {
- return errors.New("received empty parameters")
+ return ErrParametersMissing
}
values := url.Values{
@@ -277,7 +343,7 @@ func (api *Client) DeleteFileCommentContext(ctx context.Context, fileID, comment
"file": {fileID},
"id": {commentID},
}
- _, err = fileRequest(ctx, api.httpclient, "files.comments.delete", values, api.debug)
+ _, err = api.fileRequest(ctx, "files.comments.delete", values)
return err
}
@@ -293,7 +359,7 @@ func (api *Client) DeleteFileContext(ctx context.Context, fileID string) (err er
"file": {fileID},
}
- _, err = fileRequest(ctx, api.httpclient, "files.delete", values, api.debug)
+ _, err = api.fileRequest(ctx, "files.delete", values)
return err
}
@@ -309,7 +375,7 @@ func (api *Client) RevokeFilePublicURLContext(ctx context.Context, fileID string
"file": {fileID},
}
- response, err := fileRequest(ctx, api.httpclient, "files.revokePublicURL", values, api.debug)
+ response, err := api.fileRequest(ctx, "files.revokePublicURL", values)
if err != nil {
return nil, err
}
@@ -328,7 +394,7 @@ func (api *Client) ShareFilePublicURLContext(ctx context.Context, fileID string)
"file": {fileID},
}
- response, err := fileRequest(ctx, api.httpclient, "files.sharedPublicURL", values, api.debug)
+ response, err := api.fileRequest(ctx, "files.sharedPublicURL", values)
if err != nil {
return nil, nil, nil, err
}
diff --git a/vendor/github.com/nlopes/slack/go.mod b/vendor/github.com/nlopes/slack/go.mod
new file mode 100644
index 000000000..87256eb17
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/go.mod
@@ -0,0 +1,9 @@
+module github.com/nlopes/slack
+
+require (
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/gorilla/websocket v1.2.0
+ github.com/pkg/errors v0.8.0
+ github.com/pmezard/go-difflib v1.0.0 // indirect
+ github.com/stretchr/testify v1.2.2
+)
diff --git a/vendor/github.com/nlopes/slack/go.sum b/vendor/github.com/nlopes/slack/go.sum
new file mode 100644
index 000000000..3bb45c1f8
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/go.sum
@@ -0,0 +1,22 @@
+github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/gorilla/websocket v1.2.0 h1:VJtLvh6VQym50czpZzx07z/kw9EgAxI3x1ZB8taTMQQ=
+github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
+github.com/nlopes/slack v0.1.0/go.mod h1:jVI4BBK3lSktibKahxBF74txcK2vyvkza1z/+rRnVAM=
+github.com/nlopes/slack v0.5.0 h1:NbIae8Kd0NpqaEI3iUrsuS0KbcEDhzhc939jLW5fNm0=
+github.com/nlopes/slack v0.5.0/go.mod h1:jVI4BBK3lSktibKahxBF74txcK2vyvkza1z/+rRnVAM=
+github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
+github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/victorcoder/slack-test v0.0.0-20190131110821-6f9a569c10af h1:JFxr+No3ZWgCtxnnTWCybnB/z0Iy3qLmdj3u2NV5o48=
+github.com/victorcoder/slack-test v0.0.0-20190131110821-6f9a569c10af/go.mod h1:dStM4ShMus8J3hiq66ExbbzGLkwyZ+RQJePwFhWCCvQ=
+github.com/victorcoder/slack-test v0.0.0-20190131113129-a43b3bb77f43 h1:wtFekkaAAQibpy3iE4Hhx2Gi9pZAbITOSfVP7GXk5eM=
+github.com/victorcoder/slack-test v0.0.0-20190131113129-a43b3bb77f43/go.mod h1:dStM4ShMus8J3hiq66ExbbzGLkwyZ+RQJePwFhWCCvQ=
+golang.org/x/net v0.0.0-20180108090419-434ec0c7fe37 h1:BkNcmLtAVeWe9h5k0jt24CQgaG5vb4x/doFbAiEC/Ho=
+golang.org/x/net v0.0.0-20180108090419-434ec0c7fe37/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
diff --git a/vendor/github.com/nlopes/slack/groups.go b/vendor/github.com/nlopes/slack/groups.go
index 67e78e993..233748695 100644
--- a/vendor/github.com/nlopes/slack/groups.go
+++ b/vendor/github.com/nlopes/slack/groups.go
@@ -2,14 +2,13 @@ package slack
import (
"context"
- "errors"
"net/url"
"strconv"
)
// Group contains all the information for a group
type Group struct {
- groupConversation
+ GroupConversation
IsGroup bool `json:"is_group"`
}
@@ -28,16 +27,14 @@ type groupResponseFull struct {
SlackResponse
}
-func groupRequest(ctx context.Context, client HTTPRequester, path string, values url.Values, debug bool) (*groupResponseFull, error) {
+func (api *Client) groupRequest(ctx context.Context, path string, values url.Values) (*groupResponseFull, error) {
response := &groupResponseFull{}
- err := postForm(ctx, client, SLACK_API+path, values, response, debug)
+ err := api.postMethod(ctx, path, values, response)
if err != nil {
return nil, err
}
- if !response.Ok {
- return nil, errors.New(response.Error)
- }
- return response, nil
+
+ return response, response.Err()
}
// ArchiveGroup archives a private group
@@ -52,7 +49,7 @@ func (api *Client) ArchiveGroupContext(ctx context.Context, group string) error
"channel": {group},
}
- _, err := groupRequest(ctx, api.httpclient, "groups.archive", values, api.debug)
+ _, err := api.groupRequest(ctx, "groups.archive", values)
return err
}
@@ -68,7 +65,7 @@ func (api *Client) UnarchiveGroupContext(ctx context.Context, group string) erro
"channel": {group},
}
- _, err := groupRequest(ctx, api.httpclient, "groups.unarchive", values, api.debug)
+ _, err := api.groupRequest(ctx, "groups.unarchive", values)
return err
}
@@ -84,7 +81,7 @@ func (api *Client) CreateGroupContext(ctx context.Context, group string) (*Group
"name": {group},
}
- response, err := groupRequest(ctx, api.httpclient, "groups.create", values, api.debug)
+ response, err := api.groupRequest(ctx, "groups.create", values)
if err != nil {
return nil, err
}
@@ -109,32 +106,13 @@ func (api *Client) CreateChildGroupContext(ctx context.Context, group string) (*
"channel": {group},
}
- response, err := groupRequest(ctx, api.httpclient, "groups.createChild", values, api.debug)
+ response, err := api.groupRequest(ctx, "groups.createChild", values)
if err != nil {
return nil, err
}
return &response.Group, nil
}
-// CloseGroup closes a private group
-func (api *Client) CloseGroup(group string) (bool, bool, error) {
- return api.CloseGroupContext(context.Background(), group)
-}
-
-// CloseGroupContext closes a private group with a custom context
-func (api *Client) CloseGroupContext(ctx context.Context, group string) (bool, bool, error) {
- values := url.Values{
- "token": {api.token},
- "channel": {group},
- }
-
- response, err := imRequest(ctx, api.httpclient, "groups.close", values, api.debug)
- if err != nil {
- return false, false, err
- }
- return response.NoOp, response.AlreadyClosed, nil
-}
-
// GetGroupHistory fetches all the history for a private group
func (api *Client) GetGroupHistory(group string, params HistoryParameters) (*History, error) {
return api.GetGroupHistoryContext(context.Background(), group, params)
@@ -170,7 +148,7 @@ func (api *Client) GetGroupHistoryContext(ctx context.Context, group string, par
}
}
- response, err := groupRequest(ctx, api.httpclient, "groups.history", values, api.debug)
+ response, err := api.groupRequest(ctx, "groups.history", values)
if err != nil {
return nil, err
}
@@ -190,7 +168,7 @@ func (api *Client) InviteUserToGroupContext(ctx context.Context, group, user str
"user": {user},
}
- response, err := groupRequest(ctx, api.httpclient, "groups.invite", values, api.debug)
+ response, err := api.groupRequest(ctx, "groups.invite", values)
if err != nil {
return nil, false, err
}
@@ -209,7 +187,7 @@ func (api *Client) LeaveGroupContext(ctx context.Context, group string) (err err
"channel": {group},
}
- _, err = groupRequest(ctx, api.httpclient, "groups.leave", values, api.debug)
+ _, err = api.groupRequest(ctx, "groups.leave", values)
return err
}
@@ -226,7 +204,7 @@ func (api *Client) KickUserFromGroupContext(ctx context.Context, group, user str
"user": {user},
}
- _, err = groupRequest(ctx, api.httpclient, "groups.kick", values, api.debug)
+ _, err = api.groupRequest(ctx, "groups.kick", values)
return err
}
@@ -244,7 +222,7 @@ func (api *Client) GetGroupsContext(ctx context.Context, excludeArchived bool) (
values.Add("exclude_archived", "1")
}
- response, err := groupRequest(ctx, api.httpclient, "groups.list", values, api.debug)
+ response, err := api.groupRequest(ctx, "groups.list", values)
if err != nil {
return nil, err
}
@@ -259,11 +237,12 @@ func (api *Client) GetGroupInfo(group string) (*Group, error) {
// GetGroupInfoContext retrieves the given group with a custom context
func (api *Client) GetGroupInfoContext(ctx context.Context, group string) (*Group, error) {
values := url.Values{
- "token": {api.token},
- "channel": {group},
+ "token": {api.token},
+ "channel": {group},
+ "include_locale": {strconv.FormatBool(true)},
}
- response, err := groupRequest(ctx, api.httpclient, "groups.info", values, api.debug)
+ response, err := api.groupRequest(ctx, "groups.info", values)
if err != nil {
return nil, err
}
@@ -288,7 +267,7 @@ func (api *Client) SetGroupReadMarkContext(ctx context.Context, group, ts string
"ts": {ts},
}
- _, err = groupRequest(ctx, api.httpclient, "groups.mark", values, api.debug)
+ _, err = api.groupRequest(ctx, "groups.mark", values)
return err
}
@@ -304,7 +283,7 @@ func (api *Client) OpenGroupContext(ctx context.Context, group string) (bool, bo
"channel": {group},
}
- response, err := groupRequest(ctx, api.httpclient, "groups.open", values, api.debug)
+ response, err := api.groupRequest(ctx, "groups.open", values)
if err != nil {
return false, false, err
}
@@ -328,7 +307,7 @@ func (api *Client) RenameGroupContext(ctx context.Context, group, name string) (
// XXX: the created entry in this call returns a string instead of a number
// so I may have to do some workaround to solve it.
- response, err := groupRequest(ctx, api.httpclient, "groups.rename", values, api.debug)
+ response, err := api.groupRequest(ctx, "groups.rename", values)
if err != nil {
return nil, err
}
@@ -348,7 +327,7 @@ func (api *Client) SetGroupPurposeContext(ctx context.Context, group, purpose st
"purpose": {purpose},
}
- response, err := groupRequest(ctx, api.httpclient, "groups.setPurpose", values, api.debug)
+ response, err := api.groupRequest(ctx, "groups.setPurpose", values)
if err != nil {
return "", err
}
@@ -368,7 +347,7 @@ func (api *Client) SetGroupTopicContext(ctx context.Context, group, topic string
"topic": {topic},
}
- response, err := groupRequest(ctx, api.httpclient, "groups.setTopic", values, api.debug)
+ response, err := api.groupRequest(ctx, "groups.setTopic", values)
if err != nil {
return "", err
}
diff --git a/vendor/github.com/nlopes/slack/im.go b/vendor/github.com/nlopes/slack/im.go
index fa8b09593..ee784fef1 100644
--- a/vendor/github.com/nlopes/slack/im.go
+++ b/vendor/github.com/nlopes/slack/im.go
@@ -2,7 +2,6 @@ package slack
import (
"context"
- "errors"
"net/url"
"strconv"
)
@@ -23,22 +22,18 @@ type imResponseFull struct {
// IM contains information related to the Direct Message channel
type IM struct {
- conversation
- IsIM bool `json:"is_im"`
- User string `json:"user"`
- IsUserDeleted bool `json:"is_user_deleted"`
+ Conversation
+ IsUserDeleted bool `json:"is_user_deleted"`
}
-func imRequest(ctx context.Context, client HTTPRequester, path string, values url.Values, debug bool) (*imResponseFull, error) {
+func (api *Client) imRequest(ctx context.Context, path string, values url.Values) (*imResponseFull, error) {
response := &imResponseFull{}
- err := postSlackMethod(ctx, client, path, values, response, debug)
+ err := api.postMethod(ctx, path, values, response)
if err != nil {
return nil, err
}
- if !response.Ok {
- return nil, errors.New(response.Error)
- }
- return response, nil
+
+ return response, response.Err()
}
// CloseIMChannel closes the direct message channel
@@ -53,7 +48,7 @@ func (api *Client) CloseIMChannelContext(ctx context.Context, channel string) (b
"channel": {channel},
}
- response, err := imRequest(ctx, api.httpclient, "im.close", values, api.debug)
+ response, err := api.imRequest(ctx, "im.close", values)
if err != nil {
return false, false, err
}
@@ -74,7 +69,7 @@ func (api *Client) OpenIMChannelContext(ctx context.Context, user string) (bool,
"user": {user},
}
- response, err := imRequest(ctx, api.httpclient, "im.open", values, api.debug)
+ response, err := api.imRequest(ctx, "im.open", values)
if err != nil {
return false, false, "", err
}
@@ -94,7 +89,7 @@ func (api *Client) MarkIMChannelContext(ctx context.Context, channel, ts string)
"ts": {ts},
}
- _, err := imRequest(ctx, api.httpclient, "im.mark", values, api.debug)
+ _, err := api.imRequest(ctx, "im.mark", values)
return err
}
@@ -133,7 +128,7 @@ func (api *Client) GetIMHistoryContext(ctx context.Context, channel string, para
}
}
- response, err := imRequest(ctx, api.httpclient, "im.history", values, api.debug)
+ response, err := api.imRequest(ctx, "im.history", values)
if err != nil {
return nil, err
}
@@ -151,7 +146,7 @@ func (api *Client) GetIMChannelsContext(ctx context.Context) ([]IM, error) {
"token": {api.token},
}
- response, err := imRequest(ctx, api.httpclient, "im.list", values, api.debug)
+ response, err := api.imRequest(ctx, "im.list", values)
if err != nil {
return nil, err
}
diff --git a/vendor/github.com/nlopes/slack/interactions.go b/vendor/github.com/nlopes/slack/interactions.go
new file mode 100644
index 000000000..5433463d0
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/interactions.go
@@ -0,0 +1,98 @@
+package slack
+
+import (
+ "encoding/json"
+)
+
+// InteractionType type of interactions
+type InteractionType string
+
+// ActionType type represents the type of action (attachment, block, etc.)
+type actionType string
+
+// action is an interface that should be implemented by all callback action types
+type action interface {
+ actionType() actionType
+}
+
+// Types of interactions that can be received.
+const (
+ InteractionTypeDialogCancellation = InteractionType("dialog_cancellation")
+ InteractionTypeDialogSubmission = InteractionType("dialog_submission")
+ InteractionTypeDialogSuggestion = InteractionType("dialog_suggestion")
+ InteractionTypeInteractionMessage = InteractionType("interactive_message")
+ InteractionTypeMessageAction = InteractionType("message_action")
+ InteractionTypeBlockActions = InteractionType("block_actions")
+)
+
+// InteractionCallback is sent from slack when a user interactions with a button or dialog.
+type InteractionCallback struct {
+ Type InteractionType `json:"type"`
+ Token string `json:"token"`
+ CallbackID string `json:"callback_id"`
+ ResponseURL string `json:"response_url"`
+ TriggerID string `json:"trigger_id"`
+ ActionTs string `json:"action_ts"`
+ Team Team `json:"team"`
+ Channel Channel `json:"channel"`
+ User User `json:"user"`
+ OriginalMessage Message `json:"original_message"`
+ Message Message `json:"message"`
+ Name string `json:"name"`
+ Value string `json:"value"`
+ MessageTs string `json:"message_ts"`
+ AttachmentID string `json:"attachment_id"`
+ ActionCallback ActionCallbacks `json:"actions"`
+ DialogSubmissionCallback
+}
+
+// ActionCallback is a convenience struct defined to allow dynamic unmarshalling of
+// the "actions" value in Slack's JSON response, which varies depending on block type
+type ActionCallbacks struct {
+ AttachmentActions []*AttachmentAction
+ BlockActions []*BlockAction
+}
+
+// UnmarshalJSON implements the Marshaller interface in order to delegate
+// marshalling and allow for proper type assertion when decoding the response
+func (a *ActionCallbacks) UnmarshalJSON(data []byte) error {
+ var raw []json.RawMessage
+ err := json.Unmarshal(data, &raw)
+ if err != nil {
+ return err
+ }
+
+ for _, r := range raw {
+ var obj map[string]interface{}
+ err := json.Unmarshal(r, &obj)
+ if err != nil {
+ return err
+ }
+
+ if _, ok := obj["block_id"].(string); ok {
+ action, err := unmarshalAction(r, &BlockAction{})
+ if err != nil {
+ return err
+ }
+
+ a.BlockActions = append(a.BlockActions, action.(*BlockAction))
+ return nil
+ }
+
+ action, err := unmarshalAction(r, &AttachmentAction{})
+ if err != nil {
+ return err
+ }
+ a.AttachmentActions = append(a.AttachmentActions, action.(*AttachmentAction))
+ }
+
+ return nil
+}
+
+func unmarshalAction(r json.RawMessage, callbackAction action) (action, error) {
+ err := json.Unmarshal(r, callbackAction)
+ if err != nil {
+ return nil, err
+ }
+ return callbackAction, nil
+}
diff --git a/vendor/github.com/nlopes/slack/internal/errorsx/errorsx.go b/vendor/github.com/nlopes/slack/internal/errorsx/errorsx.go
new file mode 100644
index 000000000..cb850577c
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/internal/errorsx/errorsx.go
@@ -0,0 +1,8 @@
+package errorsx
+
+// String representing an error, useful for declaring string constants as errors.
+type String string
+
+func (t String) Error() string {
+ return string(t)
+}
diff --git a/vendor/github.com/nlopes/slack/internal/timex/timex.go b/vendor/github.com/nlopes/slack/internal/timex/timex.go
new file mode 100644
index 000000000..40063f738
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/internal/timex/timex.go
@@ -0,0 +1,18 @@
+package timex
+
+import "time"
+
+// Max returns the maximum duration
+func Max(values ...time.Duration) time.Duration {
+ var (
+ max time.Duration
+ )
+
+ for _, v := range values {
+ if v > max {
+ max = v
+ }
+ }
+
+ return max
+}
diff --git a/vendor/github.com/nlopes/slack/logger.go b/vendor/github.com/nlopes/slack/logger.go
index 501d1672d..6a3533a97 100644
--- a/vendor/github.com/nlopes/slack/logger.go
+++ b/vendor/github.com/nlopes/slack/logger.go
@@ -2,52 +2,59 @@ package slack
import (
"fmt"
- "sync"
)
-// SetLogger let's library users supply a logger, so that api debugging
-// can be logged along with the application's debugging info.
-func SetLogger(l logProvider) {
- loggerMutex.Lock()
- logger = ilogger{logProvider: l}
- loggerMutex.Unlock()
-}
-
-var (
- loggerMutex = new(sync.Mutex)
- logger logInternal // A logger that can be set by consumers
-)
-
-// logProvider is a logger interface compatible with both stdlib and some
-// 3rd party loggers such as logrus.
-type logProvider interface {
+// logger is a logger interface compatible with both stdlib and some
+// 3rd party loggers.
+type logger interface {
Output(int, string) error
}
-// logInternal represents the internal logging api we use.
-type logInternal interface {
+// ilogger represents the internal logging api we use.
+type ilogger interface {
+ logger
Print(...interface{})
Printf(string, ...interface{})
Println(...interface{})
- Output(int, string) error
}
-// ilogger implements the additional methods used by our internal logging.
-type ilogger struct {
- logProvider
+type debug interface {
+ Debug() bool
+
+ // Debugf print a formatted debug line.
+ Debugf(format string, v ...interface{})
+ // Debugln print a debug line.
+ Debugln(v ...interface{})
+}
+
+// internalLog implements the additional methods used by our internal logging.
+type internalLog struct {
+ logger
}
// Println replicates the behaviour of the standard logger.
-func (t ilogger) Println(v ...interface{}) {
+func (t internalLog) Println(v ...interface{}) {
t.Output(2, fmt.Sprintln(v...))
}
// Printf replicates the behaviour of the standard logger.
-func (t ilogger) Printf(format string, v ...interface{}) {
+func (t internalLog) Printf(format string, v ...interface{}) {
t.Output(2, fmt.Sprintf(format, v...))
}
// Print replicates the behaviour of the standard logger.
-func (t ilogger) Print(v ...interface{}) {
+func (t internalLog) Print(v ...interface{}) {
t.Output(2, fmt.Sprint(v...))
}
+
+type discard struct{}
+
+func (t discard) Debug() bool {
+ return false
+}
+
+// Debugf print a formatted debug line.
+func (t discard) Debugf(format string, v ...interface{}) {}
+
+// Debugln print a debug line.
+func (t discard) Debugln(v ...interface{}) {}
diff --git a/vendor/github.com/nlopes/slack/messages.go b/vendor/github.com/nlopes/slack/messages.go
index 6551dd4f0..6cd3627af 100644
--- a/vendor/github.com/nlopes/slack/messages.go
+++ b/vendor/github.com/nlopes/slack/messages.go
@@ -4,17 +4,19 @@ package slack
type OutgoingMessage struct {
ID int `json:"id"`
// channel ID
- Channel string `json:"channel,omitempty"`
- Text string `json:"text,omitempty"`
- Type string `json:"type,omitempty"`
- ThreadTimestamp string `json:"thread_ts,omitempty"`
- ThreadBroadcast bool `json:"reply_broadcast,omitempty"`
+ Channel string `json:"channel,omitempty"`
+ Text string `json:"text,omitempty"`
+ Type string `json:"type,omitempty"`
+ ThreadTimestamp string `json:"thread_ts,omitempty"`
+ ThreadBroadcast bool `json:"reply_broadcast,omitempty"`
+ IDs []string `json:"ids,omitempty"`
}
// Message is an auxiliary type to allow us to have a message containing sub messages
type Message struct {
Msg
SubMessage *Msg `json:"message,omitempty"`
+ PreviousMessage *Msg `json:"previous_message,omitempty"`
}
// Msg contains information about a slack message
@@ -91,6 +93,9 @@ type Msg struct {
ResponseType string `json:"response_type,omitempty"`
ReplaceOriginal bool `json:"replace_original"`
DeleteOriginal bool `json:"delete_original"`
+
+ // Block type Message
+ Blocks Blocks `json:"blocks,omitempty"`
}
// Icon is used for bot messages
@@ -147,6 +152,15 @@ func (rtm *RTM) NewOutgoingMessage(text string, channelID string, options ...RTM
return &msg
}
+// NewSubscribeUserPresence prepares an OutgoingMessage that the user can
+// use to subscribe presence events for the specified users.
+func (rtm *RTM) NewSubscribeUserPresence(ids []string) *OutgoingMessage {
+ return &OutgoingMessage{
+ Type: "presence_sub",
+ IDs: ids,
+ }
+}
+
// NewTypingMessage prepares an OutgoingMessage that the user can
// use to send as a typing indicator. Use this function to properly set the
// messageID.
@@ -174,5 +188,4 @@ func RTMsgOptionBroadcast() RTMsgOption {
return func(msg *OutgoingMessage) {
msg.ThreadBroadcast = true
}
-
}
diff --git a/vendor/github.com/nlopes/slack/misc.go b/vendor/github.com/nlopes/slack/misc.go
index 691033849..301be9795 100644
--- a/vendor/github.com/nlopes/slack/misc.go
+++ b/vendor/github.com/nlopes/slack/misc.go
@@ -19,6 +19,7 @@ import (
"time"
)
+// SlackResponse handles parsing out errors from the web api.
type SlackResponse struct {
Ok bool `json:"ok"`
Error string `json:"error"`
@@ -47,64 +48,89 @@ type statusCodeError struct {
}
func (t statusCodeError) Error() string {
- // TODO: this is a bad error string, should clean it up with a breaking changes
- // merger.
- return fmt.Sprintf("Slack server error: %s.", t.Status)
+ return fmt.Sprintf("slack server error: %s", t.Status)
}
func (t statusCodeError) HTTPStatusCode() int {
return t.Code
}
+func (t statusCodeError) Retryable() bool {
+ if t.Code >= 500 || t.Code == http.StatusTooManyRequests {
+ return true
+ }
+ return false
+}
+
+// RateLimitedError represents the rate limit respond from slack
type RateLimitedError struct {
RetryAfter time.Duration
}
func (e *RateLimitedError) Error() string {
- return fmt.Sprintf("Slack rate limit exceeded, retry after %s", e.RetryAfter)
+ return fmt.Sprintf("slack rate limit exceeded, retry after %s", e.RetryAfter)
}
-func fileUploadReq(ctx context.Context, path, fieldname, filename string, values url.Values, r io.Reader) (*http.Request, error) {
- body := &bytes.Buffer{}
- wr := multipart.NewWriter(body)
+func (e *RateLimitedError) Retryable() bool {
+ return true
+}
- ioWriter, err := wr.CreateFormFile(fieldname, filename)
+func fileUploadReq(ctx context.Context, path string, values url.Values, r io.Reader) (*http.Request, error) {
+ req, err := http.NewRequest("POST", path, r)
if err != nil {
- wr.Close()
return nil, err
}
- _, err = io.Copy(ioWriter, r)
+ req = req.WithContext(ctx)
+
+ req.URL.RawQuery = (values).Encode()
+ return req, nil
+}
+
+func downloadFile(client httpClient, token string, downloadURL string, writer io.Writer, d debug) error {
+ if downloadURL == "" {
+ return fmt.Errorf("received empty download URL")
+ }
+
+ req, err := http.NewRequest("GET", downloadURL, &bytes.Buffer{})
if err != nil {
- wr.Close()
- return nil, err
+ return err
}
- // Close the multipart writer or the footer won't be written
- wr.Close()
- req, err := http.NewRequest("POST", path, body)
- req = req.WithContext(ctx)
+
+ var bearer = "Bearer " + token
+ req.Header.Add("Authorization", bearer)
+ req.WithContext(context.Background())
+
+ resp, err := client.Do(req)
if err != nil {
- return nil, err
+ return err
}
- req.Header.Add("Content-Type", wr.FormDataContentType())
- req.URL.RawQuery = (values).Encode()
- return req, nil
+
+ defer resp.Body.Close()
+
+ err = checkStatusCode(resp, d)
+ if err != nil {
+ return err
+ }
+
+ _, err = io.Copy(writer, resp.Body)
+
+ return err
}
-func parseResponseBody(body io.ReadCloser, intf interface{}, debug bool) error {
+func parseResponseBody(body io.ReadCloser, intf interface{}, d debug) error {
response, err := ioutil.ReadAll(body)
if err != nil {
return err
}
- // FIXME: will be api.Debugf
- if debug {
- logger.Printf("parseResponseBody: %s\n", string(response))
+ if d.Debug() {
+ d.Debugln("parseResponseBody", string(response))
}
return json.Unmarshal(response, intf)
}
-func postLocalWithMultipartResponse(ctx context.Context, client HTTPRequester, path, fpath, fieldname string, values url.Values, intf interface{}, debug bool) error {
+func postLocalWithMultipartResponse(ctx context.Context, client httpClient, path, fpath, fieldname string, values url.Values, intf interface{}, d debug) error {
fullpath, err := filepath.Abs(fpath)
if err != nil {
return err
@@ -114,39 +140,57 @@ func postLocalWithMultipartResponse(ctx context.Context, client HTTPRequester, p
return err
}
defer file.Close()
- return postWithMultipartResponse(ctx, client, path, filepath.Base(fpath), fieldname, values, file, intf, debug)
+ return postWithMultipartResponse(ctx, client, path, filepath.Base(fpath), fieldname, values, file, intf, d)
}
-func postWithMultipartResponse(ctx context.Context, client HTTPRequester, path, name, fieldname string, values url.Values, r io.Reader, intf interface{}, debug bool) error {
- req, err := fileUploadReq(ctx, SLACK_API+path, fieldname, name, values, r)
+func postWithMultipartResponse(ctx context.Context, client httpClient, path, name, fieldname string, values url.Values, r io.Reader, intf interface{}, d debug) error {
+ pipeReader, pipeWriter := io.Pipe()
+ wr := multipart.NewWriter(pipeWriter)
+ errc := make(chan error)
+ go func() {
+ defer pipeWriter.Close()
+ ioWriter, err := wr.CreateFormFile(fieldname, name)
+ if err != nil {
+ errc <- err
+ return
+ }
+ _, err = io.Copy(ioWriter, r)
+ if err != nil {
+ errc <- err
+ return
+ }
+ if err = wr.Close(); err != nil {
+ errc <- err
+ return
+ }
+ }()
+ req, err := fileUploadReq(ctx, path, values, pipeReader)
if err != nil {
return err
}
+ req.Header.Add("Content-Type", wr.FormDataContentType())
req = req.WithContext(ctx)
resp, err := client.Do(req)
+
if err != nil {
return err
}
defer resp.Body.Close()
- if resp.StatusCode == http.StatusTooManyRequests {
- retry, err := strconv.ParseInt(resp.Header.Get("Retry-After"), 10, 64)
- if err != nil {
- return err
- }
- return &RateLimitedError{time.Duration(retry) * time.Second}
+ err = checkStatusCode(resp, d)
+ if err != nil {
+ return err
}
- // Slack seems to send an HTML body along with 5xx error codes. Don't parse it.
- if resp.StatusCode != http.StatusOK {
- logResponse(resp, debug)
- return statusCodeError{Code: resp.StatusCode, Status: resp.Status}
+ select {
+ case err = <-errc:
+ return err
+ default:
+ return parseResponseBody(resp.Body, intf, d)
}
-
- return parseResponseBody(resp.Body, intf, debug)
}
-func doPost(ctx context.Context, client HTTPRequester, req *http.Request, intf interface{}, debug bool) error {
+func doPost(ctx context.Context, client httpClient, req *http.Request, intf interface{}, d debug) error {
req = req.WithContext(ctx)
resp, err := client.Do(req)
if err != nil {
@@ -154,25 +198,16 @@ func doPost(ctx context.Context, client HTTPRequester, req *http.Request, intf i
}
defer resp.Body.Close()
- if resp.StatusCode == http.StatusTooManyRequests {
- retry, err := strconv.ParseInt(resp.Header.Get("Retry-After"), 10, 64)
- if err != nil {
- return err
- }
- return &RateLimitedError{time.Duration(retry) * time.Second}
- }
-
- // Slack seems to send an HTML body along with 5xx error codes. Don't parse it.
- if resp.StatusCode != http.StatusOK {
- logResponse(resp, debug)
- return statusCodeError{Code: resp.StatusCode, Status: resp.Status}
+ err = checkStatusCode(resp, d)
+ if err != nil {
+ return err
}
- return parseResponseBody(resp.Body, intf, debug)
+ return parseResponseBody(resp.Body, intf, d)
}
// post JSON.
-func postJSON(ctx context.Context, client HTTPRequester, endpoint, token string, json []byte, intf interface{}, debug bool) error {
+func postJSON(ctx context.Context, client httpClient, endpoint, token string, json []byte, intf interface{}, d debug) error {
reqBody := bytes.NewBuffer(json)
req, err := http.NewRequest("POST", endpoint, reqBody)
if err != nil {
@@ -180,38 +215,43 @@ func postJSON(ctx context.Context, client HTTPRequester, endpoint, token string,
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
- return doPost(ctx, client, req, intf, debug)
+ return doPost(ctx, client, req, intf, d)
}
// post a url encoded form.
-func postForm(ctx context.Context, client HTTPRequester, endpoint string, values url.Values, intf interface{}, debug bool) error {
+func postForm(ctx context.Context, client httpClient, endpoint string, values url.Values, intf interface{}, d debug) error {
reqBody := strings.NewReader(values.Encode())
req, err := http.NewRequest("POST", endpoint, reqBody)
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
- return doPost(ctx, client, req, intf, debug)
+ return doPost(ctx, client, req, intf, d)
}
-// post to a slack web method.
-func postSlackMethod(ctx context.Context, client HTTPRequester, path string, values url.Values, intf interface{}, debug bool) error {
- return postForm(ctx, client, SLACK_API+path, values, intf, debug)
+func getResource(ctx context.Context, client httpClient, endpoint string, values url.Values, intf interface{}, d debug) error {
+ req, err := http.NewRequest("GET", endpoint, nil)
+ if err != nil {
+ return err
+ }
+ req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
+ req.URL.RawQuery = values.Encode()
+
+ return doPost(ctx, client, req, intf, d)
}
-func parseAdminResponse(ctx context.Context, client HTTPRequester, method string, teamName string, values url.Values, intf interface{}, debug bool) error {
- endpoint := fmt.Sprintf(SLACK_WEB_API_FORMAT, teamName, method, time.Now().Unix())
- return postForm(ctx, client, endpoint, values, intf, debug)
+func parseAdminResponse(ctx context.Context, client httpClient, method string, teamName string, values url.Values, intf interface{}, d debug) error {
+ endpoint := fmt.Sprintf(WEBAPIURLFormat, teamName, method, time.Now().Unix())
+ return postForm(ctx, client, endpoint, values, intf, d)
}
-func logResponse(resp *http.Response, debug bool) error {
- if debug {
+func logResponse(resp *http.Response, d debug) error {
+ if d.Debug() {
text, err := httputil.DumpResponse(resp, true)
if err != nil {
return err
}
-
- logger.Print(string(text))
+ d.Debugln(string(text))
}
return nil
@@ -225,12 +265,6 @@ func okJSONHandler(rw http.ResponseWriter, r *http.Request) {
rw.Write(response)
}
-type errorString string
-
-func (t errorString) Error() string {
- return string(t)
-}
-
// timerReset safely reset a timer, see time.Timer.Reset for details.
func timerReset(t *time.Timer, d time.Duration) {
if !t.Stop() {
@@ -238,3 +272,21 @@ func timerReset(t *time.Timer, d time.Duration) {
}
t.Reset(d)
}
+
+func checkStatusCode(resp *http.Response, d debug) error {
+ if resp.StatusCode == http.StatusTooManyRequests {
+ retry, err := strconv.ParseInt(resp.Header.Get("Retry-After"), 10, 64)
+ if err != nil {
+ return err
+ }
+ return &RateLimitedError{time.Duration(retry) * time.Second}
+ }
+
+ // Slack seems to send an HTML body along with 5xx error codes. Don't parse it.
+ if resp.StatusCode != http.StatusOK {
+ logResponse(resp, d)
+ return statusCodeError{Code: resp.StatusCode, Status: resp.Status}
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/nlopes/slack/oauth.go b/vendor/github.com/nlopes/slack/oauth.go
index 378af4a54..29d6dce91 100644
--- a/vendor/github.com/nlopes/slack/oauth.go
+++ b/vendor/github.com/nlopes/slack/oauth.go
@@ -2,10 +2,10 @@ package slack
import (
"context"
- "errors"
"net/url"
)
+// OAuthResponseIncomingWebhook ...
type OAuthResponseIncomingWebhook struct {
URL string `json:"url"`
Channel string `json:"channel"`
@@ -13,11 +13,13 @@ type OAuthResponseIncomingWebhook struct {
ConfigurationURL string `json:"configuration_url"`
}
+// OAuthResponseBot ...
type OAuthResponseBot struct {
BotUserID string `json:"bot_user_id"`
BotAccessToken string `json:"bot_access_token"`
}
+// OAuthResponse ...
type OAuthResponse struct {
AccessToken string `json:"access_token"`
Scope string `json:"scope"`
@@ -30,24 +32,24 @@ type OAuthResponse struct {
}
// GetOAuthToken retrieves an AccessToken
-func GetOAuthToken(clientID, clientSecret, code, redirectURI string, debug bool) (accessToken string, scope string, err error) {
- return GetOAuthTokenContext(context.Background(), clientID, clientSecret, code, redirectURI, debug)
+func GetOAuthToken(client httpClient, clientID, clientSecret, code, redirectURI string) (accessToken string, scope string, err error) {
+ return GetOAuthTokenContext(context.Background(), client, clientID, clientSecret, code, redirectURI)
}
// GetOAuthTokenContext retrieves an AccessToken with a custom context
-func GetOAuthTokenContext(ctx context.Context, clientID, clientSecret, code, redirectURI string, debug bool) (accessToken string, scope string, err error) {
- response, err := GetOAuthResponseContext(ctx, clientID, clientSecret, code, redirectURI, debug)
+func GetOAuthTokenContext(ctx context.Context, client httpClient, clientID, clientSecret, code, redirectURI string) (accessToken string, scope string, err error) {
+ response, err := GetOAuthResponseContext(ctx, client, clientID, clientSecret, code, redirectURI)
if err != nil {
return "", "", err
}
return response.AccessToken, response.Scope, nil
}
-func GetOAuthResponse(clientID, clientSecret, code, redirectURI string, debug bool) (resp *OAuthResponse, err error) {
- return GetOAuthResponseContext(context.Background(), clientID, clientSecret, code, redirectURI, debug)
+func GetOAuthResponse(client httpClient, clientID, clientSecret, code, redirectURI string) (resp *OAuthResponse, err error) {
+ return GetOAuthResponseContext(context.Background(), client, clientID, clientSecret, code, redirectURI)
}
-func GetOAuthResponseContext(ctx context.Context, clientID, clientSecret, code, redirectURI string, debug bool) (resp *OAuthResponse, err error) {
+func GetOAuthResponseContext(ctx context.Context, client httpClient, clientID, clientSecret, code, redirectURI string) (resp *OAuthResponse, err error) {
values := url.Values{
"client_id": {clientID},
"client_secret": {clientSecret},
@@ -55,12 +57,8 @@ func GetOAuthResponseContext(ctx context.Context, clientID, clientSecret, code,
"redirect_uri": {redirectURI},
}
response := &OAuthResponse{}
- err = postSlackMethod(ctx, customHTTPClient, "oauth.access", values, response, debug)
- if err != nil {
+ if err = postForm(ctx, client, APIURL+"oauth.access", values, response, discard{}); err != nil {
return nil, err
}
- if !response.Ok {
- return nil, errors.New(response.Error)
- }
- return response, nil
+ return response, response.Err()
}
diff --git a/vendor/github.com/nlopes/slack/pins.go b/vendor/github.com/nlopes/slack/pins.go
index 34863f17b..ef97c8dfb 100644
--- a/vendor/github.com/nlopes/slack/pins.go
+++ b/vendor/github.com/nlopes/slack/pins.go
@@ -34,7 +34,7 @@ func (api *Client) AddPinContext(ctx context.Context, channel string, item ItemR
}
response := &SlackResponse{}
- if err := postSlackMethod(ctx, api.httpclient, "pins.add", values, response, api.debug); err != nil {
+ if err := api.postMethod(ctx, "pins.add", values, response); err != nil {
return err
}
@@ -63,7 +63,7 @@ func (api *Client) RemovePinContext(ctx context.Context, channel string, item It
}
response := &SlackResponse{}
- if err := postSlackMethod(ctx, api.httpclient, "pins.remove", values, response, api.debug); err != nil {
+ if err := api.postMethod(ctx, "pins.remove", values, response); err != nil {
return err
}
@@ -83,7 +83,7 @@ func (api *Client) ListPinsContext(ctx context.Context, channel string) ([]Item,
}
response := &listPinsResponseFull{}
- err := postSlackMethod(ctx, api.httpclient, "pins.list", values, response, api.debug)
+ err := api.postMethod(ctx, "pins.list", values, response)
if err != nil {
return nil, nil, err
}
diff --git a/vendor/github.com/nlopes/slack/reactions.go b/vendor/github.com/nlopes/slack/reactions.go
index 5eabde637..2a9bd42e7 100644
--- a/vendor/github.com/nlopes/slack/reactions.go
+++ b/vendor/github.com/nlopes/slack/reactions.go
@@ -2,7 +2,6 @@ package slack
import (
"context"
- "errors"
"net/url"
"strconv"
)
@@ -155,7 +154,7 @@ func (api *Client) AddReactionContext(ctx context.Context, name string, item Ite
}
response := &SlackResponse{}
- if err := postSlackMethod(ctx, api.httpclient, "reactions.add", values, response, api.debug); err != nil {
+ if err := api.postMethod(ctx, "reactions.add", values, response); err != nil {
return err
}
@@ -189,7 +188,7 @@ func (api *Client) RemoveReactionContext(ctx context.Context, name string, item
}
response := &SlackResponse{}
- if err := postSlackMethod(ctx, api.httpclient, "reactions.remove", values, response, api.debug); err != nil {
+ if err := api.postMethod(ctx, "reactions.remove", values, response); err != nil {
return err
}
@@ -223,12 +222,14 @@ func (api *Client) GetReactionsContext(ctx context.Context, item ItemRef, params
}
response := &getReactionsResponseFull{}
- if err := postSlackMethod(ctx, api.httpclient, "reactions.get", values, response, api.debug); err != nil {
+ if err := api.postMethod(ctx, "reactions.get", values, response); err != nil {
return nil, err
}
- if !response.Ok {
- return nil, errors.New(response.Error)
+
+ if err := response.Err(); err != nil {
+ return nil, err
}
+
return response.extractReactions(), nil
}
@@ -256,12 +257,14 @@ func (api *Client) ListReactionsContext(ctx context.Context, params ListReaction
}
response := &listReactionsResponseFull{}
- err := postSlackMethod(ctx, api.httpclient, "reactions.list", values, response, api.debug)
+ err := api.postMethod(ctx, "reactions.list", values, response)
if err != nil {
return nil, nil, err
}
- if !response.Ok {
- return nil, nil, errors.New(response.Error)
+
+ if err := response.Err(); err != nil {
+ return nil, nil, err
}
+
return response.extractReactedItems(), &response.Paging, nil
}
diff --git a/vendor/github.com/nlopes/slack/reminders.go b/vendor/github.com/nlopes/slack/reminders.go
new file mode 100644
index 000000000..9b905387e
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/reminders.go
@@ -0,0 +1,75 @@
+package slack
+
+import (
+ "context"
+ "net/url"
+ "time"
+)
+
+type Reminder struct {
+ ID string `json:"id"`
+ Creator string `json:"creator"`
+ User string `json:"user"`
+ Text string `json:"text"`
+ Recurring bool `json:"recurring"`
+ Time time.Time `json:"time"`
+ CompleteTS int `json:"complete_ts"`
+}
+
+type reminderResp struct {
+ SlackResponse
+ Reminder Reminder `json:"reminder"`
+}
+
+func (api *Client) doReminder(ctx context.Context, path string, values url.Values) (*Reminder, error) {
+ response := &reminderResp{}
+ if err := api.postMethod(ctx, path, values, response); err != nil {
+ return nil, err
+ }
+ return &response.Reminder, response.Err()
+}
+
+// AddChannelReminder adds a reminder for a channel.
+//
+// See https://api.slack.com/methods/reminders.add (NOTE: the ability to set
+// reminders on a channel is currently undocumented but has been tested to
+// work)
+func (api *Client) AddChannelReminder(channelID, text, time string) (*Reminder, error) {
+ values := url.Values{
+ "token": {api.token},
+ "text": {text},
+ "time": {time},
+ "channel": {channelID},
+ }
+ return api.doReminder(context.Background(), "reminders.add", values)
+}
+
+// AddUserReminder adds a reminder for a user.
+//
+// See https://api.slack.com/methods/reminders.add (NOTE: the ability to set
+// reminders on a channel is currently undocumented but has been tested to
+// work)
+func (api *Client) AddUserReminder(userID, text, time string) (*Reminder, error) {
+ values := url.Values{
+ "token": {api.token},
+ "text": {text},
+ "time": {time},
+ "user": {userID},
+ }
+ return api.doReminder(context.Background(), "reminders.add", values)
+}
+
+// DeleteReminder deletes an existing reminder.
+//
+// See https://api.slack.com/methods/reminders.delete
+func (api *Client) DeleteReminder(id string) error {
+ values := url.Values{
+ "token": {api.token},
+ "reminder": {id},
+ }
+ response := &SlackResponse{}
+ if err := api.postMethod(context.Background(), "reminders.delete", values, response); err != nil {
+ return err
+ }
+ return response.Err()
+}
diff --git a/vendor/github.com/nlopes/slack/rtm.go b/vendor/github.com/nlopes/slack/rtm.go
index 41a136ebb..09cb51c3a 100644
--- a/vendor/github.com/nlopes/slack/rtm.go
+++ b/vendor/github.com/nlopes/slack/rtm.go
@@ -38,7 +38,7 @@ func (api *Client) StartRTM() (info *Info, websocketURL string, err error) {
// To have a fully managed Websocket connection, use `NewRTM`, and call `ManageConnection()` on it.
func (api *Client) StartRTMContext(ctx context.Context) (info *Info, websocketURL string, err error) {
response := &infoResponseFull{}
- err = postSlackMethod(ctx, api.httpclient, "rtm.start", url.Values{"token": {api.token}}, response, api.debug)
+ err = api.postMethod(ctx, "rtm.start", url.Values{"token": {api.token}}, response)
if err != nil {
return nil, "", err
}
@@ -63,7 +63,7 @@ func (api *Client) ConnectRTM() (info *Info, websocketURL string, err error) {
// To have a fully managed Websocket connection, use `NewRTM`, and call `ManageConnection()` on it.
func (api *Client) ConnectRTMContext(ctx context.Context) (info *Info, websocketURL string, err error) {
response := &infoResponseFull{}
- err = postSlackMethod(ctx, api.httpclient, "rtm.connect", url.Values{"token": {api.token}}, response, api.debug)
+ err = api.postMethod(ctx, "rtm.connect", url.Values{"token": {api.token}}, response)
if err != nil {
api.Debugf("Failed to connect to RTM: %s", err)
return nil, "", err
@@ -100,6 +100,13 @@ func RTMOptionPingInterval(d time.Duration) RTMOption {
}
}
+// RTMOptionConnParams installs parameters to embed into the connection URL.
+func RTMOptionConnParams(connParams url.Values) RTMOption {
+ return func(rtm *RTM) {
+ rtm.connParams = connParams
+ }
+}
+
// NewRTM returns a RTM, which provides a fully managed connection to
// Slack's websocket-based Real-Time Messaging protocol.
func (api *Client) NewRTM(options ...RTMOption) *RTM {
@@ -109,10 +116,9 @@ func (api *Client) NewRTM(options ...RTMOption) *RTM {
outgoingMessages: make(chan OutgoingMessage, 20),
pingInterval: defaultPingInterval,
pingDeadman: time.NewTimer(deadmanDuration(defaultPingInterval)),
- isConnected: false,
- wasIntentional: true,
killChannel: make(chan bool),
- disconnected: make(chan struct{}, 1),
+ disconnected: make(chan struct{}),
+ disconnectedm: &sync.Once{},
forcePing: make(chan bool),
rawEvents: make(chan json.RawMessage),
idGen: NewSafeID(1),
@@ -125,14 +131,3 @@ func (api *Client) NewRTM(options ...RTMOption) *RTM {
return result
}
-
-// NewRTMWithOptions Deprecated just use NewRTM(RTMOptionsUseStart(true))
-// returns a RTM, which provides a fully managed connection to
-// Slack's websocket-based Real-Time Messaging protocol.
-// This also allows to configure various options available for RTM API.
-func (api *Client) NewRTMWithOptions(options *RTMOptions) *RTM {
- if options != nil {
- return api.NewRTM(RTMOptionUseStart(options.UseRTMStart))
- }
- return api.NewRTM()
-}
diff --git a/vendor/github.com/nlopes/slack/search.go b/vendor/github.com/nlopes/slack/search.go
index e858952f4..f4c68f709 100644
--- a/vendor/github.com/nlopes/slack/search.go
+++ b/vendor/github.com/nlopes/slack/search.go
@@ -2,7 +2,6 @@ package slack
import (
"context"
- "errors"
"net/url"
"strconv"
)
@@ -104,14 +103,12 @@ func (api *Client) _search(ctx context.Context, path, query string, params Searc
}
response = &searchResponseFull{}
- err := postSlackMethod(ctx, api.httpclient, path, values, response, api.debug)
+ err := api.postMethod(ctx, path, values, response)
if err != nil {
return nil, err
}
- if !response.Ok {
- return nil, errors.New(response.Error)
- }
- return response, nil
+
+ return response, response.Err()
}
diff --git a/vendor/github.com/nlopes/slack/security.go b/vendor/github.com/nlopes/slack/security.go
index 50201d997..dbe8fb2d9 100644
--- a/vendor/github.com/nlopes/slack/security.go
+++ b/vendor/github.com/nlopes/slack/security.go
@@ -1,47 +1,100 @@
-package slack
-
-import (
- "crypto/hmac"
- "crypto/sha256"
- "encoding/hex"
- "errors"
- "fmt"
- "hash"
- "net/http"
-)
-
-// SecretsVerifier contains the information needed to verify that the request comes from Slack
-type SecretsVerifier struct {
- slackSig string
- timeStamp string
- hmac hash.Hash
-}
-
-// NewSecretsVerifier returns a SecretsVerifier object in exchange for an http.Header object and signing secret
-func NewSecretsVerifier(header http.Header, signingSecret string) (SecretsVerifier, error) {
- if header["X-Slack-Signature"][0] == "" || header["X-Slack-Request-Timestamp"][0] == "" {
- return SecretsVerifier{}, errors.New("Headers are empty, cannot create SecretsVerifier")
- }
-
- hash := hmac.New(sha256.New, []byte(signingSecret))
- hash.Write([]byte(fmt.Sprintf("v0:%s:", header["X-Slack-Request-Timestamp"][0])))
- return SecretsVerifier{
- slackSig: header["X-Slack-Signature"][0],
- timeStamp: header["X-Slack-Request-Timestamp"][0],
- hmac: hash,
- }, nil
-}
-
-func (v *SecretsVerifier) Write(body []byte) (n int, err error) {
- return v.hmac.Write(body)
-}
-
-// Ensure compares the signature sent from Slack with the actual computed hash to judge validity
-func (v SecretsVerifier) Ensure() error {
- computed := "v0=" + string(hex.EncodeToString(v.hmac.Sum(nil)))
- if computed == v.slackSig {
- return nil
- }
-
- return fmt.Errorf("Expected signing signature: %s, but computed: %s", v.slackSig, computed)
-}
+package slack
+
+import (
+ "crypto/hmac"
+ "crypto/sha256"
+ "encoding/hex"
+ "fmt"
+ "hash"
+ "net/http"
+ "strconv"
+ "strings"
+ "time"
+)
+
+// Signature headers
+const (
+ hSignature = "X-Slack-Signature"
+ hTimestamp = "X-Slack-Request-Timestamp"
+)
+
+// SecretsVerifier contains the information needed to verify that the request comes from Slack
+type SecretsVerifier struct {
+ signature []byte
+ hmac hash.Hash
+}
+
+func unsafeSignatureVerifier(header http.Header, secret string) (_ SecretsVerifier, err error) {
+ var (
+ bsignature []byte
+ )
+
+ signature := header.Get(hSignature)
+ stimestamp := header.Get(hTimestamp)
+
+ if signature == "" || stimestamp == "" {
+ return SecretsVerifier{}, ErrMissingHeaders
+ }
+
+ if bsignature, err = hex.DecodeString(strings.TrimPrefix(signature, "v0=")); err != nil {
+ return SecretsVerifier{}, err
+ }
+
+ hash := hmac.New(sha256.New, []byte(secret))
+ if _, err = hash.Write([]byte(fmt.Sprintf("v0:%s:", stimestamp))); err != nil {
+ return SecretsVerifier{}, err
+ }
+
+ return SecretsVerifier{
+ signature: bsignature,
+ hmac: hash,
+ }, nil
+}
+
+// NewSecretsVerifier returns a SecretsVerifier object in exchange for an http.Header object and signing secret
+func NewSecretsVerifier(header http.Header, secret string) (sv SecretsVerifier, err error) {
+ var (
+ timestamp int64
+ )
+
+ stimestamp := header.Get(hTimestamp)
+
+ if sv, err = unsafeSignatureVerifier(header, secret); err != nil {
+ return SecretsVerifier{}, err
+ }
+
+ if timestamp, err = strconv.ParseInt(stimestamp, 10, 64); err != nil {
+ return SecretsVerifier{}, err
+ }
+
+ diff := absDuration(time.Since(time.Unix(timestamp, 0)))
+ if diff > 5*time.Minute {
+ return SecretsVerifier{}, ErrExpiredTimestamp
+ }
+
+ return sv, err
+}
+
+func (v *SecretsVerifier) Write(body []byte) (n int, err error) {
+ return v.hmac.Write(body)
+}
+
+// Ensure compares the signature sent from Slack with the actual computed hash to judge validity
+func (v SecretsVerifier) Ensure() error {
+ computed := v.hmac.Sum(nil)
+ // use hmac.Equal prevent leaking timing information.
+ if hmac.Equal(computed, v.signature) {
+ return nil
+ }
+
+ return fmt.Errorf("Expected signing signature: %s, but computed: %s", hex.EncodeToString(v.signature), hex.EncodeToString(computed))
+}
+
+func abs64(n int64) int64 {
+ y := n >> 63
+ return (n ^ y) - y
+}
+
+func absDuration(n time.Duration) time.Duration {
+ return time.Duration(abs64(int64(n)))
+}
diff --git a/vendor/github.com/nlopes/slack/slack.go b/vendor/github.com/nlopes/slack/slack.go
index 6d1e7de9c..c7b60110a 100644
--- a/vendor/github.com/nlopes/slack/slack.go
+++ b/vendor/github.com/nlopes/slack/slack.go
@@ -2,7 +2,6 @@ package slack
import (
"context"
- "errors"
"fmt"
"log"
"net/http"
@@ -10,31 +9,18 @@ import (
"os"
)
-// Added as a var so that we can change this for testing purposes
-var SLACK_API string = "https://slack.com/api/"
-var SLACK_WEB_API_FORMAT string = "https://%s.slack.com/api/users.admin.%s?t=%s"
-
-// HTTPClient sets a custom http.Client
-// deprecated: in favor of SetHTTPClient()
-var HTTPClient = &http.Client{}
-
-var customHTTPClient HTTPRequester = HTTPClient
+const (
+ // APIURL of the slack api.
+ APIURL = "https://slack.com/api/"
+ // WEBAPIURLFormat ...
+ WEBAPIURLFormat = "https://%s.slack.com/api/users.admin.%s?t=%d"
+)
-// HTTPRequester defines the minimal interface needed for an http.Client to be implemented.
-//
-// Use it in conjunction with the SetHTTPClient function to allow for other capabilities
-// like a tracing http.Client
-type HTTPRequester interface {
+// httpClient defines the minimal interface needed for an http.Client to be implemented.
+type httpClient interface {
Do(*http.Request) (*http.Response, error)
}
-// SetHTTPClient allows you to specify a custom http.Client
-// Use this instead of the package level HTTPClient variable if you want to use a custom client like the
-// Stackdriver Trace HTTPClient https://godoc.org/cloud.google.com/go/trace#HTTPClient
-func SetHTTPClient(client HTTPRequester) {
- customHTTPClient = client
-}
-
// ResponseMetadata holds pagination metadata
type ResponseMetadata struct {
Cursor string `json:"next_cursor"`
@@ -48,12 +34,15 @@ func (t *ResponseMetadata) initialize() *ResponseMetadata {
return &ResponseMetadata{}
}
+// AuthTestResponse ...
type AuthTestResponse struct {
URL string `json:"url"`
Team string `json:"team"`
User string `json:"user"`
TeamID string `json:"team_id"`
UserID string `json:"user_id"`
+ // EnterpriseID is only returned when an enterprise id present
+ EnterpriseID string `json:"enterprise_id,omitempty"`
}
type authTestResponseFull struct {
@@ -61,28 +50,51 @@ type authTestResponseFull struct {
AuthTestResponse
}
+// Client for the slack api.
type Client struct {
token string
- info Info
+ endpoint string
debug bool
- httpclient HTTPRequester
+ log ilogger
+ httpclient httpClient
}
// Option defines an option for a Client
type Option func(*Client)
// OptionHTTPClient - provide a custom http client to the slack client.
-func OptionHTTPClient(c HTTPRequester) func(*Client) {
- return func(s *Client) {
- s.httpclient = c
+func OptionHTTPClient(client httpClient) func(*Client) {
+ return func(c *Client) {
+ c.httpclient = client
+ }
+}
+
+// OptionDebug enable debugging for the client
+func OptionDebug(b bool) func(*Client) {
+ return func(c *Client) {
+ c.debug = b
+ }
+}
+
+// OptionLog set logging for client.
+func OptionLog(l logger) func(*Client) {
+ return func(c *Client) {
+ c.log = internalLog{logger: l}
}
}
+// OptionAPIURL set the url for the client. only useful for testing.
+func OptionAPIURL(u string) func(*Client) {
+ return func(c *Client) { c.endpoint = u }
+}
+
// New builds a slack client from the provided token and options.
func New(token string, options ...Option) *Client {
s := &Client{
token: token,
- httpclient: customHTTPClient,
+ endpoint: APIURL,
+ httpclient: &http.Client{},
+ log: log.New(os.Stderr, "nlopes/slack", log.LstdFlags|log.Lshortfile),
}
for _, opt := range options {
@@ -98,43 +110,42 @@ func (api *Client) AuthTest() (response *AuthTestResponse, error error) {
}
// AuthTestContext tests if the user is able to do authenticated requests or not with a custom context
-func (api *Client) AuthTestContext(ctx context.Context) (response *AuthTestResponse, error error) {
+func (api *Client) AuthTestContext(ctx context.Context) (response *AuthTestResponse, err error) {
api.Debugf("Challenging auth...")
responseFull := &authTestResponseFull{}
- err := postSlackMethod(ctx, api.httpclient, "auth.test", url.Values{"token": {api.token}}, responseFull, api.debug)
+ err = api.postMethod(ctx, "auth.test", url.Values{"token": {api.token}}, responseFull)
if err != nil {
- api.Debugf("failed to test for auth: %s", err)
return nil, err
}
- if !responseFull.Ok {
- api.Debugf("auth response was not Ok: %s", responseFull.Error)
- return nil, errors.New(responseFull.Error)
- }
-
- api.Debugf("Auth challenge was successful with response %+v", responseFull.AuthTestResponse)
- return &responseFull.AuthTestResponse, nil
-}
-// SetDebug switches the api into debug mode
-// When in debug mode, it logs various info about what its doing
-// If you ever use this in production, don't call SetDebug(true)
-func (api *Client) SetDebug(debug bool) {
- api.debug = debug
- if debug && logger == nil {
- SetLogger(log.New(os.Stdout, "nlopes/slack", log.LstdFlags|log.Lshortfile))
- }
+ return &responseFull.AuthTestResponse, responseFull.Err()
}
// Debugf print a formatted debug line.
func (api *Client) Debugf(format string, v ...interface{}) {
if api.debug {
- logger.Output(2, fmt.Sprintf(format, v...))
+ api.log.Output(2, fmt.Sprintf(format, v...))
}
}
// Debugln print a debug line.
func (api *Client) Debugln(v ...interface{}) {
if api.debug {
- logger.Output(2, fmt.Sprintln(v...))
+ api.log.Output(2, fmt.Sprintln(v...))
}
}
+
+// Debug returns if debug is enabled.
+func (api *Client) Debug() bool {
+ return api.debug
+}
+
+// post to a slack web method.
+func (api *Client) postMethod(ctx context.Context, path string, values url.Values, intf interface{}) error {
+ return postForm(ctx, api.httpclient, api.endpoint+path, values, intf, api)
+}
+
+// get a slack web method.
+func (api *Client) getMethod(ctx context.Context, path string, values url.Values, intf interface{}) error {
+ return getResource(ctx, api.httpclient, api.endpoint+path, values, intf, api)
+}
diff --git a/vendor/github.com/nlopes/slack/slacktest/Makefile b/vendor/github.com/nlopes/slack/slacktest/Makefile
new file mode 100644
index 000000000..7ea9f2b03
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/slacktest/Makefile
@@ -0,0 +1,33 @@
+EXAMPLES := $(shell find examples/ -maxdepth 1 -type d -exec sh -c 'echo $(basename {})' \;)
+EXLIST := $(subst examples/,,$(EXAMPLES))
+
+ifeq ($(TRAVIS_BUILD_DIR),)
+ GOPATH := $(GOPATH)
+else
+ GOPATH := $(GOPATH):$(TRAVIS_BUILD_DIR)
+endif
+
+all: chmod clean lint test coverage $(EXLIST)
+
+# this chmod is a side effect of some windows-development related issues
+chmod:
+ chmod +x script/*
+
+lint:
+ @script/lint
+
+test:
+ @script/test
+
+coverage:
+ @script/coverage
+
+$(EXLIST):
+ @echo $@
+ @go test -v ./examples/$@
+ @gocov test ./examples/$@ | gocov report
+
+clean:
+ @rm -rf bin/ pkg/
+
+.PHONY: all chmod clean lint test coverage $(EXLIST)
diff --git a/vendor/github.com/nlopes/slack/slacktest/README.md b/vendor/github.com/nlopes/slack/slacktest/README.md
new file mode 100644
index 000000000..c35d7f610
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/slacktest/README.md
@@ -0,0 +1,5 @@
+# slacktest
+
+code in this package was shamelessly copied from https://github.com/lusis/slack-test.
+since we were unable to get a response from the maintainer and its lack of license
+have left us in an odd state. but wanted to move it here for maintenance purposes.
diff --git a/vendor/github.com/nlopes/slack/slacktest/data.go b/vendor/github.com/nlopes/slack/slacktest/data.go
new file mode 100644
index 000000000..52cb65762
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/slacktest/data.go
@@ -0,0 +1,189 @@
+package slacktest
+
+import (
+ "fmt"
+
+ slack "github.com/nlopes/slack"
+)
+
+const defaultBotName = "TestSlackBot"
+const defaultBotID = "U023BECGF"
+const defaultTeamID = "T024BE7LD"
+const defaultNonBotUserID = "W012A3CDE"
+const defaultNonBotUserName = "Egon Spengler"
+const defaultTeamName = "SlackTest Team"
+const defaultTeamDomain = "testdomain"
+
+var defaultCreatedTs = nowAsJSONTime()
+
+var defaultTeam = &slack.Team{
+ ID: defaultTeamID,
+ Name: defaultTeamName,
+ Domain: defaultTeamDomain,
+}
+
+var defaultBotInfo = &slack.UserDetails{
+ ID: defaultBotID,
+ Name: defaultBotName,
+ Created: defaultCreatedTs,
+ ManualPresence: "true",
+ Prefs: slack.UserPrefs{},
+}
+
+var okWebResponse = slack.SlackResponse{
+ Ok: true,
+}
+
+var defaultChannelsListJSON = fmt.Sprintf(`
+ {
+ "ok": true,
+ "channels": [%s, %s]
+ }
+ `, defaultGeneralChannelJSON, defaultExtraChannelJSON)
+
+var defaultGroupsListJSON = fmt.Sprintf(`
+ {
+ "ok": true,
+ "groups": [%s]
+ }
+ `, defaultGroupJSON)
+
+var defaultAuthTestJSON = fmt.Sprintf(`
+ {
+ "ok": true,
+ "url": "https://localhost.localdomain/",
+ "team": "%s",
+ "user": "%s",
+ "team_id": "%s",
+ "user_id": "%s"
+ }
+`, defaultTeamName, defaultNonBotUserName, defaultTeamID, defaultNonBotUserID)
+
+var defaultUsersInfoJSON = fmt.Sprintf(`
+ {
+ "ok":true,
+ %s
+ }
+ `, defaultNonBotUser)
+
+var defaultGeneralChannelJSON = fmt.Sprintf(`
+ {
+ "id": "C024BE91L",
+ "name": "general",
+ "is_channel": true,
+ "created": %d,
+ "creator": "%s",
+ "is_archived": false,
+ "is_general": true,
+
+ "members": [
+ "W012A3CDE"
+ ],
+
+ "topic": {
+ "value": "Fun times",
+ "creator": "%s",
+ "last_set": %d
+ },
+ "purpose": {
+ "value": "This channel is for fun",
+ "creator": "%s",
+ "last_set": %d
+ },
+
+ "is_member": true
+ }
+`, nowAsJSONTime(), defaultNonBotUserID, defaultNonBotUserID, nowAsJSONTime(), defaultNonBotUserID, nowAsJSONTime())
+
+var defaultExtraChannelJSON = fmt.Sprintf(`
+ {
+ "id": "C024BE92L",
+ "name": "bot-playground",
+ "is_channel": true,
+ "created": %d,
+ "creator": "%s",
+ "is_archived": false,
+ "is_general": true,
+
+ "members": [
+ "W012A3CDE"
+ ],
+
+ "topic": {
+ "value": "Fun times",
+ "creator": "%s",
+ "last_set": %d
+ },
+ "purpose": {
+ "value": "This channel is for fun",
+ "creator": "%s",
+ "last_set": %d
+ },
+
+ "is_member": true
+ }
+`, nowAsJSONTime(), defaultNonBotUserID, defaultNonBotUserID, nowAsJSONTime(), defaultNonBotUserID, nowAsJSONTime())
+
+var defaultGroupJSON = fmt.Sprintf(`{
+ "id": "G024BE91L",
+ "name": "secretplans",
+ "is_group": true,
+ "created": %d,
+ "creator": "%s",
+ "is_archived": false,
+ "members": [
+ "W012A3CDE"
+ ],
+ "topic": {
+ "value": "Secret plans on hold",
+ "creator": "%s",
+ "last_set": %d
+ },
+ "purpose": {
+ "value": "Discuss secret plans that no-one else should know",
+ "creator": "%s",
+ "last_set": %d
+ }
+}`, nowAsJSONTime(), defaultNonBotUserID, defaultNonBotUserID, nowAsJSONTime(), defaultNonBotUserID, nowAsJSONTime())
+
+var defaultNonBotUser = fmt.Sprintf(`
+ "user": {
+ "id": "%s",
+ "team_id": "%s",
+ "name": "spengler",
+ "deleted": false,
+ "color": "9f69e7",
+ "real_name": "%s",
+ "tz": "America/Los_Angeles",
+ "tz_label": "Pacific Daylight Time",
+ "tz_offset": -25200,
+ "profile": {
+ "avatar_hash": "ge3b51ca72de",
+ "status_text": "Print is dead",
+ "status_emoji": ":books:",
+ "real_name": "%s",
+ "display_name": "spengler",
+ "real_name_normalized": "%s",
+ "display_name_normalized": "spengler",
+ "email": "spengler@ghostbusters.example.com",
+ "image_24": "https://localhost.localdomain/avatar/e3b51ca72dee4ef87916ae2b9240df50.jpg",
+ "image_32": "https://localhost.localdomain/avatar/e3b51ca72dee4ef87916ae2b9240df50.jpg",
+ "image_48": "https://localhost.localdomain/avatar/e3b51ca72dee4ef87916ae2b9240df50.jpg",
+ "image_72": "https://localhost.localdomain/avatar/e3b51ca72dee4ef87916ae2b9240df50.jpg",
+ "image_192": "https://localhost.localdomain/avatar/e3b51ca72dee4ef87916ae2b9240df50.jpg",
+ "image_512": "https://localhost.localdomain/avatar/e3b51ca72dee4ef87916ae2b9240df50.jpg",
+ "team": "%s"
+ },
+ "is_admin": true,
+ "is_owner": false,
+ "is_primary_owner": false,
+ "is_restricted": false,
+ "is_ultra_restricted": false,
+ "is_bot": false,
+ "is_stranger": false,
+ "updated": 1502138686,
+ "is_app_user": false,
+ "has_2fa": false,
+ "locale": "en-US"
+ }
+ `, defaultNonBotUserID, defaultTeamID, defaultNonBotUserName, defaultNonBotUserName, defaultNonBotUserName, defaultTeamID)
diff --git a/vendor/github.com/nlopes/slack/slacktest/errors.go b/vendor/github.com/nlopes/slack/slacktest/errors.go
new file mode 100644
index 000000000..98553903c
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/slacktest/errors.go
@@ -0,0 +1,14 @@
+package slacktest
+
+import (
+ "github.com/nlopes/slack/internal/errorsx"
+)
+
+const (
+ // ErrEmptyServerToHub is the error when attempting an empty server address to the hub
+ ErrEmptyServerToHub = errorsx.String("Unable to add an empty server address to hub")
+ // ErrPassedEmptyServerAddr is the error when being passed an empty server address
+ ErrPassedEmptyServerAddr = errorsx.String("Passed an empty server address")
+ // ErrNoQueuesRegisteredForServer is the error when there are no queues for a server in the hub
+ ErrNoQueuesRegisteredForServer = errorsx.String("No queues registered for server")
+)
diff --git a/vendor/github.com/nlopes/slack/slacktest/funcs.go b/vendor/github.com/nlopes/slack/slacktest/funcs.go
new file mode 100644
index 000000000..976feb66b
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/slacktest/funcs.go
@@ -0,0 +1,138 @@
+package slacktest
+
+import (
+ "context"
+ "fmt"
+ "log"
+ "time"
+
+ websocket "github.com/gorilla/websocket"
+ slack "github.com/nlopes/slack"
+)
+
+func (sts *Server) queueForWebsocket(s, hubname string) {
+ channel, err := getHubForServer(hubname)
+ if err != nil {
+ log.Printf("Unable to get server's channels: %s", err.Error())
+ }
+ sts.seenOutboundMessages.Lock()
+ sts.seenOutboundMessages.messages = append(sts.seenOutboundMessages.messages, s)
+ sts.seenOutboundMessages.Unlock()
+ channel.sent <- s
+}
+
+func handlePendingMessages(c *websocket.Conn, hubname string) {
+ channel, err := getHubForServer(hubname)
+ if err != nil {
+ log.Printf("Unable to get server's channels: %s", err.Error())
+ return
+ }
+ for m := range channel.sent {
+ err := c.WriteMessage(websocket.TextMessage, []byte(m))
+ if err != nil {
+ log.Printf("error writing message to websocket: %s", err.Error())
+ continue
+ }
+ }
+}
+
+func (sts *Server) postProcessMessage(m, hubname string) {
+ channel, err := getHubForServer(hubname)
+ if err != nil {
+ log.Printf("Unable to get server's channels: %s", err.Error())
+ return
+ }
+ sts.seenInboundMessages.Lock()
+ sts.seenInboundMessages.messages = append(sts.seenInboundMessages.messages, m)
+ sts.seenInboundMessages.Unlock()
+ // send to firehose
+ channel.seen <- m
+}
+
+func newHub() *hub {
+ h := &hub{}
+ c := make(map[string]*messageChannels)
+ h.serverChannels = c
+ return h
+}
+
+func addServerToHub(s *Server, channels *messageChannels) error {
+ if s.ServerAddr == "" {
+ return ErrEmptyServerToHub
+ }
+ masterHub.Lock()
+ masterHub.serverChannels[s.ServerAddr] = channels
+ masterHub.Unlock()
+ return nil
+}
+
+func getHubForServer(serverAddr string) (*messageChannels, error) {
+ if serverAddr == "" {
+ return &messageChannels{}, ErrPassedEmptyServerAddr
+ }
+ masterHub.RLock()
+ defer masterHub.RUnlock()
+ channels, ok := masterHub.serverChannels[serverAddr]
+ if !ok {
+ return &messageChannels{}, ErrNoQueuesRegisteredForServer
+ }
+ return channels, nil
+}
+
+// BotNameFromContext returns the botname from a provided context
+func BotNameFromContext(ctx context.Context) string {
+ botname, ok := ctx.Value(ServerBotNameContextKey).(string)
+ if !ok {
+ return defaultBotName
+ }
+ return botname
+}
+
+// BotIDFromContext returns the bot userid from a provided context
+func BotIDFromContext(ctx context.Context) string {
+ botname, ok := ctx.Value(ServerBotIDContextKey).(string)
+ if !ok {
+ return defaultBotID
+ }
+ return botname
+}
+
+// generate a full rtminfo response for initial rtm connections
+func generateRTMInfo(ctx context.Context, wsurl string) *fullInfoSlackResponse {
+ rtmInfo := slack.Info{
+ URL: wsurl,
+ Team: defaultTeam,
+ User: defaultBotInfo,
+ }
+ rtmInfo.User.ID = BotIDFromContext(ctx)
+ rtmInfo.User.Name = BotNameFromContext(ctx)
+ return &fullInfoSlackResponse{
+ rtmInfo,
+ okWebResponse,
+ }
+}
+
+func nowAsJSONTime() slack.JSONTime {
+ return slack.JSONTime(time.Now().Unix())
+}
+
+func defaultBotInfoJSON(ctx context.Context) string {
+ botid := BotIDFromContext(ctx)
+ botname := BotNameFromContext(ctx)
+ return fmt.Sprintf(`
+ {
+ "ok":true,
+ "bot":{
+ "id": "%s",
+ "app_id": "A4H1JB4AZ",
+ "deleted": false,
+ "name": "%s",
+ "icons": {
+ "image_36": "https://localhost.localdomain/img36.png",
+ "image_48": "https://localhost.localdomain/img48.png",
+ "image_72": "https://localhost.localdomain/img72.png"
+ }
+ }
+ }
+ `, botid, botname)
+}
diff --git a/vendor/github.com/nlopes/slack/slacktest/handlers.go b/vendor/github.com/nlopes/slack/slacktest/handlers.go
new file mode 100644
index 000000000..415861de6
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/slacktest/handlers.go
@@ -0,0 +1,228 @@
+package slacktest
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "net/http"
+ "net/url"
+ "time"
+
+ websocket "github.com/gorilla/websocket"
+ slack "github.com/nlopes/slack"
+)
+
+func contextHandler(server *Server, next http.HandlerFunc) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ ctx := context.WithValue(r.Context(), ServerURLContextKey, server.GetAPIURL())
+ ctx = context.WithValue(ctx, ServerWSContextKey, server.GetWSURL())
+ ctx = context.WithValue(ctx, ServerBotNameContextKey, server.BotName)
+ ctx = context.WithValue(ctx, ServerBotChannelsContextKey, server.GetChannels())
+ ctx = context.WithValue(ctx, ServerBotGroupsContextKey, server.GetGroups())
+ ctx = context.WithValue(ctx, ServerBotHubNameContextKey, server.ServerAddr)
+ next.ServeHTTP(w, r.WithContext(ctx))
+ })
+}
+
+// handle auth.test
+func authTestHandler(w http.ResponseWriter, _ *http.Request) {
+ _, _ = w.Write([]byte(defaultAuthTestJSON))
+}
+
+func usersInfoHandler(w http.ResponseWriter, _ *http.Request) {
+ _, _ = w.Write([]byte(defaultUsersInfoJSON))
+}
+
+func botsInfoHandler(w http.ResponseWriter, r *http.Request) {
+ _, _ = w.Write([]byte(defaultBotInfoJSON(r.Context())))
+}
+
+// handle channels.list
+func listChannelsHandler(w http.ResponseWriter, _ *http.Request) {
+ _, _ = w.Write([]byte(defaultChannelsListJSON))
+}
+
+// handle groups.list
+func listGroupsHandler(w http.ResponseWriter, _ *http.Request) {
+ _, _ = w.Write([]byte(defaultGroupsListJSON))
+}
+
+// handle chat.postMessage
+func (sts *Server) postMessageHandler(w http.ResponseWriter, r *http.Request) {
+ serverAddr := r.Context().Value(ServerBotHubNameContextKey).(string)
+ data, err := ioutil.ReadAll(r.Body)
+ if err != nil {
+ msg := fmt.Sprintf("error reading body: %s", err.Error())
+ log.Printf(msg)
+ http.Error(w, msg, http.StatusInternalServerError)
+ return
+ }
+ values, vErr := url.ParseQuery(string(data))
+ if vErr != nil {
+ msg := fmt.Sprintf("Unable to decode query params: %s", vErr.Error())
+ log.Printf(msg)
+ http.Error(w, msg, http.StatusInternalServerError)
+ return
+ }
+
+ ts := time.Now().Unix()
+ resp := fmt.Sprintf(`{"channel":"%s","ts":"%d", "text":"%s", "ok": true}`, values.Get("channel"), ts, values.Get("text"))
+ m := slack.Message{}
+ m.Type = "message"
+ m.Channel = values.Get("channel")
+ m.Timestamp = fmt.Sprintf("%d", ts)
+ m.Text = values.Get("text")
+ if values.Get("as_user") != "true" {
+ m.User = defaultNonBotUserID
+ m.Username = defaultNonBotUserName
+ } else {
+ m.User = BotIDFromContext(r.Context())
+ m.Username = BotNameFromContext(r.Context())
+ }
+ attachments := values.Get("attachments")
+ if attachments != "" {
+ decoded, err := url.QueryUnescape(attachments)
+ if err != nil {
+ msg := fmt.Sprintf("Unable to decode attachments: %s", err.Error())
+ log.Printf(msg)
+ http.Error(w, msg, http.StatusInternalServerError)
+ return
+ }
+ var attaches []slack.Attachment
+ aJErr := json.Unmarshal([]byte(decoded), &attaches)
+ if aJErr != nil {
+ msg := fmt.Sprintf("Unable to decode attachments string to json: %s", aJErr.Error())
+ log.Printf(msg)
+ http.Error(w, msg, http.StatusInternalServerError)
+ return
+ }
+ m.Attachments = attaches
+ }
+ jsonMessage, jsonErr := json.Marshal(m)
+ if jsonErr != nil {
+ msg := fmt.Sprintf("Unable to marshal message: %s", jsonErr.Error())
+ log.Printf(msg)
+ http.Error(w, msg, http.StatusInternalServerError)
+ return
+ }
+ go sts.queueForWebsocket(string(jsonMessage), serverAddr)
+ _, _ = w.Write([]byte(resp))
+}
+
+func rtmConnectHandler(w http.ResponseWriter, r *http.Request) {
+ _, err := ioutil.ReadAll(r.Body)
+ if err != nil {
+ msg := fmt.Sprintf("Error reading body: %s", err.Error())
+ log.Printf(msg)
+ http.Error(w, msg, http.StatusInternalServerError)
+ return
+ }
+ wsurl := r.Context().Value(ServerWSContextKey).(string)
+ if wsurl == "" {
+ msg := "missing webservice url from context"
+ log.Printf(msg)
+ http.Error(w, msg, http.StatusInternalServerError)
+ return
+ }
+
+ fullresponse := generateRTMInfo(r.Context(), wsurl)
+ j, jErr := json.Marshal(fullresponse)
+ if jErr != nil {
+ msg := fmt.Sprintf("Unable to marshal response: %s", jErr.Error())
+ log.Printf("Error: %s", msg)
+ http.Error(w, msg, http.StatusInternalServerError)
+ return
+ }
+ _, wErr := w.Write(j)
+ if wErr != nil {
+ log.Printf("Error writing response: %s", wErr.Error())
+ }
+}
+
+func rtmStartHandler(w http.ResponseWriter, r *http.Request) {
+ _, err := ioutil.ReadAll(r.Body)
+ if err != nil {
+ msg := fmt.Sprintf("Error reading body: %s", err.Error())
+ log.Printf(msg)
+ http.Error(w, msg, http.StatusInternalServerError)
+ return
+ }
+ wsurl := r.Context().Value(ServerWSContextKey).(string)
+ if wsurl == "" {
+ msg := "missing webservice url from context"
+ log.Printf(msg)
+ http.Error(w, msg, http.StatusInternalServerError)
+ return
+ }
+
+ fullresponse := generateRTMInfo(r.Context(), wsurl)
+ j, jErr := json.Marshal(fullresponse)
+ if jErr != nil {
+ msg := fmt.Sprintf("Unable to marshal response: %s", jErr.Error())
+ log.Printf("Error: %s", msg)
+ http.Error(w, msg, http.StatusInternalServerError)
+ return
+ }
+ _, wErr := w.Write(j)
+ if wErr != nil {
+ log.Printf("Error writing response: %s", wErr.Error())
+ }
+}
+
+func (sts *Server) wsHandler(w http.ResponseWriter, r *http.Request) {
+ upgrader := websocket.Upgrader{
+ ReadBufferSize: 1024,
+ WriteBufferSize: 1024,
+ CheckOrigin: func(r *http.Request) bool {
+ return true
+ },
+ }
+ c, err := upgrader.Upgrade(w, r, nil)
+ if err != nil {
+ msg := fmt.Sprintf("Unable to upgrade to ws connection: %s", err.Error())
+ log.Print(msg)
+ http.Error(w, msg, http.StatusInternalServerError)
+ return
+ }
+ defer func() { _ = c.Close() }()
+ serverAddr := r.Context().Value(ServerBotHubNameContextKey).(string)
+ go handlePendingMessages(c, serverAddr)
+ for {
+ mt, messageBytes, err := c.ReadMessage()
+ if err != nil {
+ log.Printf("read error: %s", err.Error())
+ continue
+ }
+ message := string(messageBytes)
+ evt := &slack.Event{}
+ if err := json.Unmarshal(messageBytes, evt); err != nil {
+ log.Printf("Error unmarshalling message: %s", err.Error())
+ log.Printf("failed message: %s", string(message))
+ continue
+ }
+ if evt.Type == "ping" {
+ p := &slack.Ping{}
+ jErr := json.Unmarshal(messageBytes, p)
+ if jErr != nil {
+ log.Printf("Unable to decode ping event: %s", jErr.Error())
+ continue
+ }
+ //log.Print("responding to slack ping")
+ pong := &slack.Pong{
+ ReplyTo: p.ID,
+ Type: "pong",
+ }
+ j, _ := json.Marshal(pong)
+ wErr := c.WriteMessage(mt, j)
+ if wErr != nil {
+ log.Printf("error writing pong back to socket: %s", wErr.Error())
+ continue
+ }
+ continue
+ } else {
+ go sts.postProcessMessage(message, serverAddr)
+ }
+ }
+}
diff --git a/vendor/github.com/nlopes/slack/slacktest/server.go b/vendor/github.com/nlopes/slack/slacktest/server.go
new file mode 100644
index 000000000..e8c4084a0
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/slacktest/server.go
@@ -0,0 +1,302 @@
+package slacktest
+
+import (
+ "encoding/json"
+ "fmt"
+ "log"
+ "net/http"
+ "net/http/httptest"
+ "time"
+
+ "github.com/nlopes/slack"
+)
+
+func newMessageChannels() *messageChannels {
+ sent := make(chan (string))
+ seen := make(chan (string))
+ mc := messageChannels{
+ seen: seen,
+ sent: sent,
+ }
+ return &mc
+}
+
+// Customize the server's responses.
+type Customize interface {
+ Handle(pattern string, handler http.HandlerFunc)
+}
+
+type binder func(Customize)
+
+// NewTestServer returns a slacktest.Server ready to be started
+func NewTestServer(custom ...binder) *Server {
+ serverChans := newMessageChannels()
+
+ channels := &serverChannels{}
+ groups := &serverGroups{}
+ s := &Server{
+ registered: map[string]struct{}{},
+ mux: http.NewServeMux(),
+ seenInboundMessages: &messageCollection{},
+ seenOutboundMessages: &messageCollection{},
+ }
+
+ for _, c := range custom {
+ c(s)
+ }
+
+ s.Handle("/ws", s.wsHandler)
+ s.Handle("/rtm.start", rtmStartHandler)
+ s.Handle("/rtm.connect", rtmConnectHandler)
+ s.Handle("/chat.postMessage", s.postMessageHandler)
+ s.Handle("/channels.list", listChannelsHandler)
+ s.Handle("/groups.list", listGroupsHandler)
+ s.Handle("/users.info", usersInfoHandler)
+ s.Handle("/bots.info", botsInfoHandler)
+ s.Handle("/auth.test", authTestHandler)
+
+ httpserver := httptest.NewUnstartedServer(s.mux)
+ addr := httpserver.Listener.Addr().String()
+
+ s.ServerAddr = addr
+ s.server = httpserver
+ s.BotName = defaultBotName
+ s.BotID = defaultBotID
+ s.SeenFeed = serverChans.seen
+ s.channels = channels
+ s.groups = groups
+
+ addErr := addServerToHub(s, serverChans)
+ if addErr != nil {
+ log.Printf("Unable to add server to hub: %s", addErr.Error())
+ }
+
+ return s
+}
+
+// Handle allow for customizing endpoints
+func (sts *Server) Handle(pattern string, handler http.HandlerFunc) {
+ if _, found := sts.registered[pattern]; found {
+ log.Printf("route already registered: %s\n", pattern)
+ return
+ }
+
+ sts.registered[pattern] = struct{}{}
+ sts.mux.Handle(pattern, contextHandler(sts, handler))
+}
+
+// GetChannels returns all the fake channels registered
+func (sts *Server) GetChannels() []slack.Channel {
+ sts.channels.RLock()
+ defer sts.channels.RUnlock()
+ return sts.channels.channels
+}
+
+// GetGroups returns all the fake groups registered
+func (sts *Server) GetGroups() []slack.Group {
+ return sts.groups.channels
+}
+
+// GetSeenInboundMessages returns all messages seen via websocket excluding pings
+func (sts *Server) GetSeenInboundMessages() []string {
+ sts.seenInboundMessages.RLock()
+ m := sts.seenInboundMessages.messages
+ sts.seenInboundMessages.RUnlock()
+ return m
+}
+
+// GetSeenOutboundMessages returns all messages seen via websocket excluding pings
+func (sts *Server) GetSeenOutboundMessages() []string {
+ sts.seenOutboundMessages.RLock()
+ m := sts.seenOutboundMessages.messages
+ sts.seenOutboundMessages.RUnlock()
+ return m
+}
+
+// SawOutgoingMessage checks if a message was sent to connected websocket clients
+func (sts *Server) SawOutgoingMessage(msg string) bool {
+ sts.seenOutboundMessages.RLock()
+ defer sts.seenOutboundMessages.RUnlock()
+ for _, m := range sts.seenOutboundMessages.messages {
+ evt := &slack.MessageEvent{}
+ jErr := json.Unmarshal([]byte(m), evt)
+ if jErr != nil {
+ continue
+ }
+
+ if evt.Text == msg {
+ return true
+ }
+ }
+ return false
+}
+
+// SawMessage checks if an incoming message was seen
+func (sts *Server) SawMessage(msg string) bool {
+ sts.seenInboundMessages.RLock()
+ defer sts.seenInboundMessages.RUnlock()
+ for _, m := range sts.seenInboundMessages.messages {
+ evt := &slack.MessageEvent{}
+ jErr := json.Unmarshal([]byte(m), evt)
+ if jErr != nil {
+ // This event isn't a message event so we'll skip it
+ continue
+ }
+ if evt.Text == msg {
+ return true
+ }
+ }
+ return false
+}
+
+// GetAPIURL returns the api url you can pass to slack.SLACK_API
+func (sts *Server) GetAPIURL() string {
+ return "http://" + sts.ServerAddr + "/"
+}
+
+// GetWSURL returns the websocket url
+func (sts *Server) GetWSURL() string {
+ return "ws://" + sts.ServerAddr + "/ws"
+}
+
+// Stop stops the test server
+func (sts *Server) Stop() {
+ sts.server.Close()
+}
+
+// Start starts the test server
+func (sts *Server) Start() {
+ log.Print("starting server")
+ sts.server.Start()
+}
+
+// SendMessageToBot sends a message addressed to the Bot
+func (sts *Server) SendMessageToBot(channel, msg string) {
+ m := slack.Message{}
+ m.Type = slack.TYPE_MESSAGE
+ m.Channel = channel
+ m.User = defaultNonBotUserID
+ m.Text = fmt.Sprintf("<@%s> %s", sts.BotID, msg)
+ m.Timestamp = fmt.Sprintf("%d", time.Now().Unix())
+ j, jErr := json.Marshal(m)
+ if jErr != nil {
+ log.Printf("Unable to marshal message for bot: %s", jErr.Error())
+ return
+ }
+ go sts.queueForWebsocket(string(j), sts.ServerAddr)
+}
+
+// SendDirectMessageToBot sends a direct message to the bot
+func (sts *Server) SendDirectMessageToBot(msg string) {
+ m := slack.Message{}
+ m.Type = slack.TYPE_MESSAGE
+ m.Channel = "D024BE91L"
+ m.User = defaultNonBotUserID
+ m.Text = msg
+ m.Timestamp = fmt.Sprintf("%d", time.Now().Unix())
+ j, jErr := json.Marshal(m)
+ if jErr != nil {
+ log.Printf("Unable to marshal private message for bot: %s", jErr.Error())
+ return
+ }
+ go sts.queueForWebsocket(string(j), sts.ServerAddr)
+}
+
+// SendMessageToChannel sends a message to a channel
+func (sts *Server) SendMessageToChannel(channel, msg string) {
+ m := slack.Message{}
+ m.Type = slack.TYPE_MESSAGE
+ m.Channel = channel
+ m.Text = msg
+ m.User = defaultNonBotUserID
+ m.Timestamp = fmt.Sprintf("%d", time.Now().Unix())
+ j, jErr := json.Marshal(m)
+ if jErr != nil {
+ log.Printf("Unable to marshal message for channel: %s", jErr.Error())
+ return
+ }
+ stringMsg := string(j)
+ go sts.queueForWebsocket(stringMsg, sts.ServerAddr)
+}
+
+// SendToWebsocket send `s` as is to connected clients.
+// This is useful for sending your own custom json to the websocket
+func (sts *Server) SendToWebsocket(s string) {
+ go sts.queueForWebsocket(s, sts.ServerAddr)
+}
+
+// SetBotName sets a custom botname
+func (sts *Server) SetBotName(b string) {
+ sts.BotName = b
+}
+
+// SendBotChannelInvite invites the bot to a channel
+func (sts *Server) SendBotChannelInvite() {
+ joinMsg := `
+ {
+ "type":"channel_joined",
+ "channel":
+ {
+ "id": "C024BE92L",
+ "name": "bot-playground",
+ "is_channel": true,
+ "created": 1360782804,
+ "creator": "W012A3CDE",
+ "is_archived": false,
+ "is_general": true,
+ "members": [
+ "W012A3CDE"
+ ],
+ "topic": {
+ "value": "Fun times",
+ "creator": "W012A3CDE",
+ "last_set": 1360782804
+ },
+ "purpose": {
+ "value": "This channel is for fun",
+ "creator": "W012A3CDE",
+ "last_set": 1360782804
+ },
+ "is_member": true
+ }
+ }`
+ sts.SendToWebsocket(joinMsg)
+}
+
+// SendBotGroupInvite invites the bot to a channel
+func (sts *Server) SendBotGroupInvite() {
+ joinMsg := `
+ {
+ "type":"group_joined",
+ "channel":
+ {
+ "id": "G024BE91L",
+ "name": "secretplans",
+ "is_group": true,
+ "created": 1360782804,
+ "creator": "W012A3CDE",
+ "is_archived": false,
+ "members": [
+ "W012A3CDE"
+ ],
+ "topic": {
+ "value": "Secret plans on hold",
+ "creator": "W012A3CDE",
+ "last_set": 1360782804
+ },
+ "purpose": {
+ "value": "Discuss secret plans that no-one else should know",
+ "creator": "W012A3CDE",
+ "last_set": 1360782804
+ }
+ }
+ }`
+ sts.SendToWebsocket(joinMsg)
+}
+
+// GetTestRTMInstance will give you an RTM instance in the context of the current fake server
+func (sts *Server) GetTestRTMInstance() *slack.RTM {
+ api := slack.New("ABCEFG", slack.OptionAPIURL(sts.GetAPIURL()))
+ rtm := api.NewRTM()
+ return rtm
+}
diff --git a/vendor/github.com/nlopes/slack/slacktest/types.go b/vendor/github.com/nlopes/slack/slacktest/types.go
new file mode 100644
index 000000000..43497a705
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/slacktest/types.go
@@ -0,0 +1,81 @@
+package slacktest
+
+import (
+ "log"
+ "net/http"
+ "net/http/httptest"
+ "sync"
+
+ "github.com/nlopes/slack"
+)
+
+type contextKey string
+
+// ServerURLContextKey is the context key to store the server's url
+const ServerURLContextKey contextKey = "__SERVER_URL__"
+
+// ServerWSContextKey is the context key to store the server's ws url
+const ServerWSContextKey contextKey = "__SERVER_WS_URL__"
+
+// ServerBotNameContextKey is the bot name
+const ServerBotNameContextKey contextKey = "__SERVER_BOTNAME__"
+
+// ServerBotIDContextKey is the bot userid
+const ServerBotIDContextKey contextKey = "__SERVER_BOTID__"
+
+// ServerBotChannelsContextKey is the list of channels associated with the fake server
+const ServerBotChannelsContextKey contextKey = "__SERVER_CHANNELS__"
+
+// ServerBotGroupsContextKey is the list of channels associated with the fake server
+const ServerBotGroupsContextKey contextKey = "__SERVER_GROUPS__"
+
+// ServerBotHubNameContextKey is the context key for passing along the server name registered in the hub
+const ServerBotHubNameContextKey contextKey = "__SERVER_HUBNAME__"
+
+var masterHub = newHub()
+
+type hub struct {
+ sync.RWMutex
+ serverChannels map[string]*messageChannels
+}
+
+type messageChannels struct {
+ seen chan (string)
+ sent chan (string)
+ posted chan (slack.Message)
+}
+type messageCollection struct {
+ sync.RWMutex
+ messages []string
+}
+
+type serverChannels struct {
+ sync.RWMutex
+ channels []slack.Channel
+}
+
+type serverGroups struct {
+ sync.RWMutex
+ channels []slack.Group
+}
+
+// Server represents a Slack Test server
+type Server struct {
+ registered map[string]struct{}
+ server *httptest.Server
+ mux *http.ServeMux
+ Logger *log.Logger
+ BotName string
+ BotID string
+ ServerAddr string
+ SeenFeed chan (string)
+ channels *serverChannels
+ groups *serverGroups
+ seenInboundMessages *messageCollection
+ seenOutboundMessages *messageCollection
+}
+
+type fullInfoSlackResponse struct {
+ slack.Info
+ slack.SlackResponse
+}
diff --git a/vendor/github.com/nlopes/slack/slackutilsx/slackutilsx.go b/vendor/github.com/nlopes/slack/slackutilsx/slackutilsx.go
index ccf5372bc..1f7b2b8c2 100644
--- a/vendor/github.com/nlopes/slack/slackutilsx/slackutilsx.go
+++ b/vendor/github.com/nlopes/slack/slackutilsx/slackutilsx.go
@@ -55,3 +55,8 @@ func EscapeMessage(message string) string {
replacer := strings.NewReplacer("&", "&", "<", "<", ">", ">")
return replacer.Replace(message)
}
+
+// Retryable errors return true.
+type Retryable interface {
+ Retryable() bool
+}
diff --git a/vendor/github.com/nlopes/slack/stars.go b/vendor/github.com/nlopes/slack/stars.go
index c1e2f6cb7..e84d0447f 100644
--- a/vendor/github.com/nlopes/slack/stars.go
+++ b/vendor/github.com/nlopes/slack/stars.go
@@ -2,7 +2,6 @@ package slack
import (
"context"
- "errors"
"net/url"
"strconv"
)
@@ -58,7 +57,7 @@ func (api *Client) AddStarContext(ctx context.Context, channel string, item Item
}
response := &SlackResponse{}
- if err := postSlackMethod(ctx, api.httpclient, "stars.add", values, response, api.debug); err != nil {
+ if err := api.postMethod(ctx, "stars.add", values, response); err != nil {
return err
}
@@ -87,7 +86,7 @@ func (api *Client) RemoveStarContext(ctx context.Context, channel string, item I
}
response := &SlackResponse{}
- if err := postSlackMethod(ctx, api.httpclient, "stars.remove", values, response, api.debug); err != nil {
+ if err := api.postMethod(ctx, "stars.remove", values, response); err != nil {
return err
}
@@ -115,13 +114,15 @@ func (api *Client) ListStarsContext(ctx context.Context, params StarsParameters)
}
response := &listResponseFull{}
- err := postSlackMethod(ctx, api.httpclient, "stars.list", values, response, api.debug)
+ err := api.postMethod(ctx, "stars.list", values, response)
if err != nil {
return nil, nil, err
}
- if !response.Ok {
- return nil, nil, errors.New(response.Error)
+
+ if err := response.Err(); err != nil {
+ return nil, nil, err
}
+
return response.Items, &response.Paging, nil
}
diff --git a/vendor/github.com/nlopes/slack/team.go b/vendor/github.com/nlopes/slack/team.go
index b6e341ebf..029e2b5bc 100644
--- a/vendor/github.com/nlopes/slack/team.go
+++ b/vendor/github.com/nlopes/slack/team.go
@@ -2,7 +2,6 @@ package slack
import (
"context"
- "errors"
"net/url"
"strconv"
)
@@ -67,44 +66,33 @@ func NewAccessLogParameters() AccessLogParameters {
}
}
-func teamRequest(ctx context.Context, client HTTPRequester, path string, values url.Values, debug bool) (*TeamResponse, error) {
+func (api *Client) teamRequest(ctx context.Context, path string, values url.Values) (*TeamResponse, error) {
response := &TeamResponse{}
- err := postSlackMethod(ctx, client, path, values, response, debug)
+ err := api.postMethod(ctx, path, values, response)
if err != nil {
return nil, err
}
- if !response.Ok {
- return nil, errors.New(response.Error)
- }
-
- return response, nil
+ return response, response.Err()
}
-func billableInfoRequest(ctx context.Context, client HTTPRequester, path string, values url.Values, debug bool) (map[string]BillingActive, error) {
+func (api *Client) billableInfoRequest(ctx context.Context, path string, values url.Values) (map[string]BillingActive, error) {
response := &BillableInfoResponse{}
- err := postSlackMethod(ctx, client, path, values, response, debug)
+ err := api.postMethod(ctx, path, values, response)
if err != nil {
return nil, err
}
- if !response.Ok {
- return nil, errors.New(response.Error)
- }
-
- return response.BillableInfo, nil
+ return response.BillableInfo, response.Err()
}
-func accessLogsRequest(ctx context.Context, client HTTPRequester, path string, values url.Values, debug bool) (*LoginResponse, error) {
+func (api *Client) accessLogsRequest(ctx context.Context, path string, values url.Values) (*LoginResponse, error) {
response := &LoginResponse{}
- err := postSlackMethod(ctx, client, path, values, response, debug)
+ err := api.postMethod(ctx, path, values, response)
if err != nil {
return nil, err
}
- if !response.Ok {
- return nil, errors.New(response.Error)
- }
- return response, nil
+ return response, response.Err()
}
// GetTeamInfo gets the Team Information of the user
@@ -118,7 +106,7 @@ func (api *Client) GetTeamInfoContext(ctx context.Context) (*TeamInfo, error) {
"token": {api.token},
}
- response, err := teamRequest(ctx, api.httpclient, "team.info", values, api.debug)
+ response, err := api.teamRequest(ctx, "team.info", values)
if err != nil {
return nil, err
}
@@ -142,24 +130,26 @@ func (api *Client) GetAccessLogsContext(ctx context.Context, params AccessLogPar
values.Add("page", strconv.Itoa(params.Page))
}
- response, err := accessLogsRequest(ctx, api.httpclient, "team.accessLogs", values, api.debug)
+ response, err := api.accessLogsRequest(ctx, "team.accessLogs", values)
if err != nil {
return nil, nil, err
}
return response.Logins, &response.Paging, nil
}
+// GetBillableInfo ...
func (api *Client) GetBillableInfo(user string) (map[string]BillingActive, error) {
return api.GetBillableInfoContext(context.Background(), user)
}
+// GetBillableInfoContext ...
func (api *Client) GetBillableInfoContext(ctx context.Context, user string) (map[string]BillingActive, error) {
values := url.Values{
"token": {api.token},
"user": {user},
}
- return billableInfoRequest(ctx, api.httpclient, "team.billableInfo", values, api.debug)
+ return api.billableInfoRequest(ctx, "team.billableInfo", values)
}
// GetBillableInfoForTeam returns the billing_active status of all users on the team.
@@ -173,5 +163,5 @@ func (api *Client) GetBillableInfoForTeamContext(ctx context.Context) (map[strin
"token": {api.token},
}
- return billableInfoRequest(ctx, api.httpclient, "team.billableInfo", values, api.debug)
+ return api.billableInfoRequest(ctx, "team.billableInfo", values)
}
diff --git a/vendor/github.com/nlopes/slack/usergroups.go b/vendor/github.com/nlopes/slack/usergroups.go
index cc9bc4ca7..f3206591d 100644
--- a/vendor/github.com/nlopes/slack/usergroups.go
+++ b/vendor/github.com/nlopes/slack/usergroups.go
@@ -2,7 +2,6 @@ package slack
import (
"context"
- "errors"
"net/url"
"strings"
)
@@ -41,16 +40,14 @@ type userGroupResponseFull struct {
SlackResponse
}
-func userGroupRequest(ctx context.Context, client HTTPRequester, path string, values url.Values, debug bool) (*userGroupResponseFull, error) {
+func (api *Client) userGroupRequest(ctx context.Context, path string, values url.Values) (*userGroupResponseFull, error) {
response := &userGroupResponseFull{}
- err := postSlackMethod(ctx, client, path, values, response, debug)
+ err := api.postMethod(ctx, path, values, response)
if err != nil {
return nil, err
}
- if !response.Ok {
- return nil, errors.New(response.Error)
- }
- return response, nil
+
+ return response, response.Err()
}
// CreateUserGroup creates a new user group
@@ -77,7 +74,7 @@ func (api *Client) CreateUserGroupContext(ctx context.Context, userGroup UserGro
values["channels"] = []string{strings.Join(userGroup.Prefs.Channels, ",")}
}
- response, err := userGroupRequest(ctx, api.httpclient, "usergroups.create", values, api.debug)
+ response, err := api.userGroupRequest(ctx, "usergroups.create", values)
if err != nil {
return UserGroup{}, err
}
@@ -96,7 +93,7 @@ func (api *Client) DisableUserGroupContext(ctx context.Context, userGroup string
"usergroup": {userGroup},
}
- response, err := userGroupRequest(ctx, api.httpclient, "usergroups.disable", values, api.debug)
+ response, err := api.userGroupRequest(ctx, "usergroups.disable", values)
if err != nil {
return UserGroup{}, err
}
@@ -115,7 +112,7 @@ func (api *Client) EnableUserGroupContext(ctx context.Context, userGroup string)
"usergroup": {userGroup},
}
- response, err := userGroupRequest(ctx, api.httpclient, "usergroups.enable", values, api.debug)
+ response, err := api.userGroupRequest(ctx, "usergroups.enable", values)
if err != nil {
return UserGroup{}, err
}
@@ -179,7 +176,7 @@ func (api *Client) GetUserGroupsContext(ctx context.Context, options ...GetUserG
values.Add("include_users", "true")
}
- response, err := userGroupRequest(ctx, api.httpclient, "usergroups.list", values, api.debug)
+ response, err := api.userGroupRequest(ctx, "usergroups.list", values)
if err != nil {
return nil, err
}
@@ -209,8 +206,12 @@ func (api *Client) UpdateUserGroupContext(ctx context.Context, userGroup UserGro
if userGroup.Description != "" {
values["description"] = []string{userGroup.Description}
}
+
+ if len(userGroup.Prefs.Channels) > 0 {
+ values["channels"] = []string{strings.Join(userGroup.Prefs.Channels, ",")}
+ }
- response, err := userGroupRequest(ctx, api.httpclient, "usergroups.update", values, api.debug)
+ response, err := api.userGroupRequest(ctx, "usergroups.update", values)
if err != nil {
return UserGroup{}, err
}
@@ -229,7 +230,7 @@ func (api *Client) GetUserGroupMembersContext(ctx context.Context, userGroup str
"usergroup": {userGroup},
}
- response, err := userGroupRequest(ctx, api.httpclient, "usergroups.users.list", values, api.debug)
+ response, err := api.userGroupRequest(ctx, "usergroups.users.list", values)
if err != nil {
return []string{}, err
}
@@ -249,7 +250,7 @@ func (api *Client) UpdateUserGroupMembersContext(ctx context.Context, userGroup
"users": {members},
}
- response, err := userGroupRequest(ctx, api.httpclient, "usergroups.users.update", values, api.debug)
+ response, err := api.userGroupRequest(ctx, "usergroups.users.update", values)
if err != nil {
return UserGroup{}, err
}
diff --git a/vendor/github.com/nlopes/slack/users.go b/vendor/github.com/nlopes/slack/users.go
index 0dd20db57..d064d6f74 100644
--- a/vendor/github.com/nlopes/slack/users.go
+++ b/vendor/github.com/nlopes/slack/users.go
@@ -3,7 +3,6 @@ package slack
import (
"context"
"encoding/json"
- "errors"
"net/url"
"strconv"
)
@@ -12,7 +11,6 @@ const (
DEFAULT_USER_PHOTO_CROP_X = -1
DEFAULT_USER_PHOTO_CROP_Y = -1
DEFAULT_USER_PHOTO_CROP_W = -1
- errPaginationComplete = errorString("pagination complete")
)
// UserProfile contains all the information details of a given user
@@ -37,6 +35,7 @@ type UserProfile struct {
ApiAppID string `json:"api_app_id,omitempty"`
StatusText string `json:"status_text,omitempty"`
StatusEmoji string `json:"status_emoji,omitempty"`
+ StatusExpiration int `json:"status_expiration"`
Team string `json:"team"`
Fields UserProfileCustomFields `json:"fields"`
}
@@ -100,28 +99,30 @@ type UserProfileCustomField struct {
// User contains all the information of a user
type User struct {
- ID string `json:"id"`
- TeamID string `json:"team_id"`
- Name string `json:"name"`
- Deleted bool `json:"deleted"`
- Color string `json:"color"`
- RealName string `json:"real_name"`
- TZ string `json:"tz,omitempty"`
- TZLabel string `json:"tz_label"`
- TZOffset int `json:"tz_offset"`
- Profile UserProfile `json:"profile"`
- IsBot bool `json:"is_bot"`
- IsAdmin bool `json:"is_admin"`
- IsOwner bool `json:"is_owner"`
- IsPrimaryOwner bool `json:"is_primary_owner"`
- IsRestricted bool `json:"is_restricted"`
- IsUltraRestricted bool `json:"is_ultra_restricted"`
- IsStranger bool `json:"is_stranger"`
- IsAppUser bool `json:"is_app_user"`
- Has2FA bool `json:"has_2fa"`
- HasFiles bool `json:"has_files"`
- Presence string `json:"presence"`
- Locale string `json:"locale"`
+ ID string `json:"id"`
+ TeamID string `json:"team_id"`
+ Name string `json:"name"`
+ Deleted bool `json:"deleted"`
+ Color string `json:"color"`
+ RealName string `json:"real_name"`
+ TZ string `json:"tz,omitempty"`
+ TZLabel string `json:"tz_label"`
+ TZOffset int `json:"tz_offset"`
+ Profile UserProfile `json:"profile"`
+ IsBot bool `json:"is_bot"`
+ IsAdmin bool `json:"is_admin"`
+ IsOwner bool `json:"is_owner"`
+ IsPrimaryOwner bool `json:"is_primary_owner"`
+ IsRestricted bool `json:"is_restricted"`
+ IsUltraRestricted bool `json:"is_ultra_restricted"`
+ IsStranger bool `json:"is_stranger"`
+ IsAppUser bool `json:"is_app_user"`
+ Has2FA bool `json:"has_2fa"`
+ HasFiles bool `json:"has_files"`
+ Presence string `json:"presence"`
+ Locale string `json:"locale"`
+ Updated JSONTime `json:"updated"`
+ Enterprise EnterpriseUser `json:"enterprise_user,omitempty"`
}
// UserPresence contains details about a user online status
@@ -152,6 +153,17 @@ type UserIdentity struct {
Image512 string `json:"image_512"`
}
+// EnterpriseUser is present when a user is part of Slack Enterprise Grid
+// https://api.slack.com/types/user#enterprise_grid_user_objects
+type EnterpriseUser struct {
+ ID string `json:"id"`
+ EnterpriseID string `json:"enterprise_id"`
+ EnterpriseName string `json:"enterprise_name"`
+ IsAdmin bool `json:"is_admin"`
+ IsOwner bool `json:"is_owner"`
+ Teams []string `json:"teams"`
+}
+
type TeamIdentity struct {
ID string `json:"id"`
Name string `json:"name"`
@@ -189,16 +201,14 @@ func NewUserSetPhotoParams() UserSetPhotoParams {
}
}
-func userRequest(ctx context.Context, client HTTPRequester, path string, values url.Values, debug bool) (*userResponseFull, error) {
+func (api *Client) userRequest(ctx context.Context, path string, values url.Values) (*userResponseFull, error) {
response := &userResponseFull{}
- err := postForm(ctx, client, SLACK_API+path, values, response, debug)
+ err := api.postMethod(ctx, path, values, response)
if err != nil {
return nil, err
}
- if !response.Ok {
- return nil, errors.New(response.Error)
- }
- return response, nil
+
+ return response, response.Err()
}
// GetUserPresence will retrieve the current presence status of given user.
@@ -213,7 +223,7 @@ func (api *Client) GetUserPresenceContext(ctx context.Context, user string) (*Us
"user": {user},
}
- response, err := userRequest(ctx, api.httpclient, "users.getPresence", values, api.debug)
+ response, err := api.userRequest(ctx, "users.getPresence", values)
if err != nil {
return nil, err
}
@@ -228,11 +238,12 @@ func (api *Client) GetUserInfo(user string) (*User, error) {
// GetUserInfoContext will retrieve the complete user information with a custom context
func (api *Client) GetUserInfoContext(ctx context.Context, user string) (*User, error) {
values := url.Values{
- "token": {api.token},
- "user": {user},
+ "token": {api.token},
+ "user": {user},
+ "include_locale": {strconv.FormatBool(true)},
}
- response, err := userRequest(ctx, api.httpclient, "users.info", values, api.debug)
+ response, err := api.userRequest(ctx, "users.info", values)
if err != nil {
return nil, err
}
@@ -304,13 +315,14 @@ func (t UserPagination) Next(ctx context.Context) (_ UserPagination, err error)
t.previousResp = t.previousResp.initialize()
values := url.Values{
- "limit": {strconv.Itoa(t.limit)},
- "presence": {strconv.FormatBool(t.presence)},
- "token": {t.c.token},
- "cursor": {t.previousResp.Cursor},
+ "limit": {strconv.Itoa(t.limit)},
+ "presence": {strconv.FormatBool(t.presence)},
+ "token": {t.c.token},
+ "cursor": {t.previousResp.Cursor},
+ "include_locale": {strconv.FormatBool(true)},
}
- if resp, err = userRequest(ctx, t.c.httpclient, "users.list", values, t.c.debug); err != nil {
+ if resp, err = t.c.userRequest(ctx, "users.list", values); err != nil {
return t, err
}
@@ -355,7 +367,7 @@ func (api *Client) GetUserByEmailContext(ctx context.Context, email string) (*Us
"token": {api.token},
"email": {email},
}
- response, err := userRequest(ctx, api.httpclient, "users.lookupByEmail", values, api.debug)
+ response, err := api.userRequest(ctx, "users.lookupByEmail", values)
if err != nil {
return nil, err
}
@@ -373,7 +385,7 @@ func (api *Client) SetUserAsActiveContext(ctx context.Context) (err error) {
"token": {api.token},
}
- _, err = userRequest(ctx, api.httpclient, "users.setActive", values, api.debug)
+ _, err = api.userRequest(ctx, "users.setActive", values)
return err
}
@@ -389,7 +401,7 @@ func (api *Client) SetUserPresenceContext(ctx context.Context, presence string)
"presence": {presence},
}
- _, err := userRequest(ctx, api.httpclient, "users.setPresence", values, api.debug)
+ _, err := api.userRequest(ctx, "users.setPresence", values)
return err
}
@@ -405,13 +417,15 @@ func (api *Client) GetUserIdentityContext(ctx context.Context) (*UserIdentityRes
}
response := &UserIdentityResponse{}
- err := postForm(ctx, api.httpclient, SLACK_API+"users.identity", values, response, api.debug)
+ err := api.postMethod(ctx, "users.identity", values, response)
if err != nil {
return nil, err
}
- if !response.Ok {
- return nil, errors.New(response.Error)
+
+ if err := response.Err(); err != nil {
+ return nil, err
}
+
return response, nil
}
@@ -436,7 +450,7 @@ func (api *Client) SetUserPhotoContext(ctx context.Context, image string, params
values.Add("crop_w", strconv.Itoa(params.CropW))
}
- err := postLocalWithMultipartResponse(ctx, api.httpclient, "users.setPhoto", image, "image", values, response, api.debug)
+ err := postLocalWithMultipartResponse(ctx, api.httpclient, api.endpoint+"users.setPhoto", image, "image", values, response, api)
if err != nil {
return err
}
@@ -456,7 +470,7 @@ func (api *Client) DeleteUserPhotoContext(ctx context.Context) error {
"token": {api.token},
}
- err := postForm(ctx, api.httpclient, SLACK_API+"users.deletePhoto", values, response, api.debug)
+ err := api.postMethod(ctx, "users.deletePhoto", values, response)
if err != nil {
return err
}
@@ -467,15 +481,16 @@ func (api *Client) DeleteUserPhotoContext(ctx context.Context) error {
// SetUserCustomStatus will set a custom status and emoji for the currently
// authenticated user. If statusEmoji is "" and statusText is not, the Slack API
// will automatically set it to ":speech_balloon:". Otherwise, if both are ""
-// the Slack API will unset the custom status/emoji.
-func (api *Client) SetUserCustomStatus(statusText, statusEmoji string) error {
- return api.SetUserCustomStatusContext(context.Background(), statusText, statusEmoji)
+// the Slack API will unset the custom status/emoji. If statusExpiration is set to 0
+// the status will not expire.
+func (api *Client) SetUserCustomStatus(statusText, statusEmoji string, statusExpiration int64) error {
+ return api.SetUserCustomStatusContext(context.Background(), statusText, statusEmoji, statusExpiration)
}
// SetUserCustomStatusContext will set a custom status and emoji for the currently authenticated user with a custom context
//
// For more information see SetUserCustomStatus
-func (api *Client) SetUserCustomStatusContext(ctx context.Context, statusText, statusEmoji string) error {
+func (api *Client) SetUserCustomStatusContext(ctx context.Context, statusText, statusEmoji string, statusExpiration int64) error {
// XXX(theckman): this anonymous struct is for making requests to the Slack
// API for setting and unsetting a User's Custom Status/Emoji. To change
// these values we must provide a JSON document as the profile POST field.
@@ -488,11 +503,13 @@ func (api *Client) SetUserCustomStatusContext(ctx context.Context, statusText, s
// - https://api.slack.com/docs/presence-and-status#custom_status
profile, err := json.Marshal(
&struct {
- StatusText string `json:"status_text"`
- StatusEmoji string `json:"status_emoji"`
+ StatusText string `json:"status_text"`
+ StatusEmoji string `json:"status_emoji"`
+ StatusExpiration int64 `json:"status_expiration"`
}{
- StatusText: statusText,
- StatusEmoji: statusEmoji,
+ StatusText: statusText,
+ StatusEmoji: statusEmoji,
+ StatusExpiration: statusExpiration,
},
)
@@ -506,15 +523,11 @@ func (api *Client) SetUserCustomStatusContext(ctx context.Context, statusText, s
}
response := &userResponseFull{}
- if err = postForm(ctx, api.httpclient, SLACK_API+"users.profile.set", values, response, api.debug); err != nil {
+ if err = api.postMethod(ctx, "users.profile.set", values, response); err != nil {
return err
}
- if !response.Ok {
- return errors.New(response.Error)
- }
-
- return nil
+ return response.Err()
}
// UnsetUserCustomStatus removes the custom status message for the currently
@@ -526,7 +539,7 @@ func (api *Client) UnsetUserCustomStatus() error {
// UnsetUserCustomStatusContext removes the custom status message for the currently authenticated user
// with a custom context. This is a convenience method that wraps (*Client).SetUserCustomStatus().
func (api *Client) UnsetUserCustomStatusContext(ctx context.Context) error {
- return api.SetUserCustomStatusContext(ctx, "", "")
+ return api.SetUserCustomStatusContext(ctx, "", "", 0)
}
// GetUserProfile retrieves a user's profile information.
@@ -547,12 +560,14 @@ func (api *Client) GetUserProfileContext(ctx context.Context, userID string, inc
}
resp := &getUserProfileResponse{}
- err := postSlackMethod(ctx, api.httpclient, "users.profile.get", values, &resp, api.debug)
+ err := api.postMethod(ctx, "users.profile.get", values, &resp)
if err != nil {
return nil, err
}
- if !resp.Ok {
- return nil, errors.New(resp.Error)
+
+ if err := resp.Err(); err != nil {
+ return nil, err
}
+
return resp.Profile, nil
}
diff --git a/vendor/github.com/nlopes/slack/webhooks.go b/vendor/github.com/nlopes/slack/webhooks.go
index 3ea69ffef..14e1b8dd9 100644
--- a/vendor/github.com/nlopes/slack/webhooks.go
+++ b/vendor/github.com/nlopes/slack/webhooks.go
@@ -9,26 +9,32 @@ import (
)
type WebhookMessage struct {
- Text string `json:"text,omitempty"`
- Attachments []Attachment `json:"attachments,omitempty"`
+ Username string `json:"username,omitempty"`
+ IconEmoji string `json:"icon_emoji,omitempty"`
+ IconURL string `json:"icon_url,omitempty"`
+ Channel string `json:"channel,omitempty"`
+ ThreadTimestamp string `json:"thread_ts,omitempty"`
+ Text string `json:"text,omitempty"`
+ Attachments []Attachment `json:"attachments,omitempty"`
+ Parse string `json:"parse,omitempty"`
}
func PostWebhook(url string, msg *WebhookMessage) error {
+ return PostWebhookCustomHTTP(url, http.DefaultClient, msg)
+}
+
+func PostWebhookCustomHTTP(url string, httpClient *http.Client, msg *WebhookMessage) error {
raw, err := json.Marshal(msg)
if err != nil {
return errors.Wrap(err, "marshal failed")
}
- response, err := http.Post(url, "application/json", bytes.NewReader(raw))
+ response, err := httpClient.Post(url, "application/json", bytes.NewReader(raw))
if err != nil {
return errors.Wrap(err, "failed to post webhook")
}
- if response.StatusCode != http.StatusOK {
- return statusCodeError{Code: response.StatusCode, Status: response.Status}
- }
-
- return nil
+ return checkStatusCode(response, discard{})
}
diff --git a/vendor/github.com/nlopes/slack/websocket.go b/vendor/github.com/nlopes/slack/websocket.go
index 242acf40e..8f19e5800 100644
--- a/vendor/github.com/nlopes/slack/websocket.go
+++ b/vendor/github.com/nlopes/slack/websocket.go
@@ -2,7 +2,7 @@ package slack
import (
"encoding/json"
- "errors"
+ "net/url"
"sync"
"time"
@@ -20,6 +20,9 @@ const (
//
// Create this element with Client's NewRTM() or NewRTMWithOptions(*RTMOptions)
type RTM struct {
+ // Client is the main API, embedded
+ Client
+
idGen IDGenerator
pingInterval time.Duration
pingDeadman *time.Timer
@@ -29,15 +32,10 @@ type RTM struct {
IncomingEvents chan RTMEvent
outgoingMessages chan OutgoingMessage
killChannel chan bool
- disconnected chan struct{} // disconnected is closed when Disconnect is invoked, regardless of connection state. Allows for ManagedConnection to not leak.
+ disconnected chan struct{}
+ disconnectedm *sync.Once
forcePing chan bool
rawEvents chan json.RawMessage
- wasIntentional bool
- isConnected bool
-
- // Client is the main API, embedded
- Client
- websocketURL string
// UserDetails upon connection
info *Info
@@ -53,40 +51,30 @@ type RTM struct {
// mu is mutex used to prevent RTM connection race conditions
mu *sync.Mutex
+
+ // connParams is a map of flags for connection parameters.
+ connParams url.Values
}
-// RTMOptions allows configuration of various options available for RTM messaging
-//
-// This structure will evolve in time so please make sure you are always using the
-// named keys for every entry available as per Go 1 compatibility promise adding fields
-// to this structure should not be considered a breaking change.
-type RTMOptions struct {
- // UseRTMStart set to true in order to use rtm.start or false to use rtm.connect
- // As of 11th July 2017 you should prefer setting this to false, see:
- // https://api.slack.com/changelog/2017-04-start-using-rtm-connect-and-stop-using-rtm-start
- UseRTMStart bool
+// signal that we are disconnected by closing the channel.
+// protect it with a mutex to ensure it only happens once.
+func (rtm *RTM) disconnect() {
+ rtm.disconnectedm.Do(func() {
+ close(rtm.disconnected)
+ })
}
// Disconnect and wait, blocking until a successful disconnection.
func (rtm *RTM) Disconnect() error {
- // avoid RTM disconnect race conditions
- rtm.mu.Lock()
- defer rtm.mu.Unlock()
-
- // always push into the disconnected channel when invoked,
+ // always push into the kill channel when invoked,
// this lets the ManagedConnection() function properly clean up.
// if the buffer is full then just continue on.
select {
- case rtm.disconnected <- struct{}{}:
- default:
+ case rtm.killChannel <- true:
+ return nil
+ case <-rtm.disconnected:
+ return ErrAlreadyDisconnected
}
-
- if !rtm.isConnected {
- return errors.New("Invalid call to Disconnect - Slack API is already disconnected")
- }
-
- rtm.killChannel <- true
- return nil
}
// GetInfo returns the info structure received when calling
@@ -110,7 +98,7 @@ func (rtm *RTM) SendMessage(msg *OutgoingMessage) {
}
func (rtm *RTM) resetDeadman() {
- timerReset(rtm.pingDeadman, deadmanDuration(rtm.pingInterval))
+ rtm.pingDeadman.Reset(deadmanDuration(rtm.pingInterval))
}
func deadmanDuration(d time.Duration) time.Duration {
diff --git a/vendor/github.com/nlopes/slack/websocket_internals.go b/vendor/github.com/nlopes/slack/websocket_internals.go
index e8374b0df..3da1612a3 100644
--- a/vendor/github.com/nlopes/slack/websocket_internals.go
+++ b/vendor/github.com/nlopes/slack/websocket_internals.go
@@ -18,6 +18,7 @@ type ConnectedEvent struct {
// ConnectionErrorEvent contains information about a connection error
type ConnectionErrorEvent struct {
Attempt int
+ Backoff time.Duration // how long we'll wait before the next attempt
ErrorObj error
}
diff --git a/vendor/github.com/nlopes/slack/websocket_managed_conn.go b/vendor/github.com/nlopes/slack/websocket_managed_conn.go
index e8ab65a1e..065979db0 100644
--- a/vendor/github.com/nlopes/slack/websocket_managed_conn.go
+++ b/vendor/github.com/nlopes/slack/websocket_managed_conn.go
@@ -5,10 +5,12 @@ import (
"fmt"
"io"
"net/http"
+ stdurl "net/url"
"reflect"
"time"
"github.com/gorilla/websocket"
+ "github.com/nlopes/slack/internal/timex"
)
// ManageConnection can be called on a Slack RTM instance returned by the
@@ -37,6 +39,7 @@ func (rtm *RTM) ManageConnection() {
if info, conn, err = rtm.connect(connectionCount, rtm.useRTMStart); err != nil {
// when the connection is unsuccessful its fatal, and we need to bail out.
rtm.Debugf("Failed to connect with RTM on try %d: %s", connectionCount, err)
+ rtm.disconnect()
return
}
@@ -44,7 +47,6 @@ func (rtm *RTM) ManageConnection() {
// and conn.
rtm.mu.Lock()
rtm.conn = conn
- rtm.isConnected = true
rtm.info = info
rtm.mu.Unlock()
@@ -55,20 +57,19 @@ func (rtm *RTM) ManageConnection() {
rtm.Debugf("RTM connection succeeded on try %d", connectionCount)
- keepRunning := make(chan bool)
- // we're now connected (or have failed fatally) so we can set up
- // listeners
- go rtm.handleIncomingEvents(keepRunning)
+ // we're now connected so we can set up listeners
+ go rtm.handleIncomingEvents()
// this should be a blocking call until the connection has ended
- rtm.handleEvents(keepRunning)
+ rtm.handleEvents()
- // after being disconnected we need to check if it was intentional
- // if not then we should try to reconnect
- if rtm.wasIntentional {
+ select {
+ case <-rtm.disconnected:
+ // after handle events returns we need to check if we're disconnected
return
+ default:
+ // otherwise continue and run the loop again to reconnect
}
- // else continue and run the loop again to connect
}
}
@@ -87,18 +88,20 @@ func (rtm *RTM) connect(connectionCount int, useRTMStart bool) (*Info, *websocke
// used to provide exponential backoff wait time with jitter before trying
// to connect to slack again
boff := &backoff{
- Min: 100 * time.Millisecond,
- Max: 5 * time.Minute,
- Factor: 2,
- Jitter: true,
+ Max: 5 * time.Minute,
}
for {
+ var (
+ backoff time.Duration
+ )
+
// send connecting event
rtm.IncomingEvents <- RTMEvent{"connecting", &ConnectingEvent{
Attempt: boff.attempts + 1,
ConnectionCount: connectionCount,
}}
+
// attempt to start the connection
info, conn, err := rtm.startRTMAndDial(useRTMStart)
if err == nil {
@@ -108,32 +111,48 @@ func (rtm *RTM) connect(connectionCount int, useRTMStart bool) (*Info, *websocke
// check for fatal errors
switch err.Error() {
case errInvalidAuth, errInactiveAccount, errMissingAuthToken:
- rtm.Debugf("Invalid auth when connecting with RTM: %s", err)
+ rtm.Debugf("invalid auth when connecting with RTM: %s", err)
rtm.IncomingEvents <- RTMEvent{"invalid_auth", &InvalidAuthEvent{}}
return nil, nil, err
default:
}
+ switch actual := err.(type) {
+ case statusCodeError:
+ if actual.Code == http.StatusNotFound {
+ rtm.Debugf("invalid auth when connecting with RTM: %s", err)
+ rtm.IncomingEvents <- RTMEvent{"invalid_auth", &InvalidAuthEvent{}}
+ return nil, nil, err
+ }
+ case *RateLimitedError:
+ backoff = actual.RetryAfter
+ default:
+ }
+
+ backoff = timex.Max(backoff, boff.Duration())
// any other errors are treated as recoverable and we try again after
// sending the event along the IncomingEvents channel
rtm.IncomingEvents <- RTMEvent{"connection_error", &ConnectionErrorEvent{
Attempt: boff.attempts,
+ Backoff: backoff,
ErrorObj: err,
}}
// check if Disconnect() has been invoked.
select {
+ case intentional := <-rtm.killChannel:
+ if intentional {
+ rtm.killConnection(intentional)
+ return nil, nil, ErrRTMDisconnected
+ }
case <-rtm.disconnected:
- rtm.IncomingEvents <- RTMEvent{"disconnected", &DisconnectedEvent{Intentional: true}}
- return nil, nil, fmt.Errorf("disconnect received while trying to connect")
+ return nil, nil, ErrRTMDisconnected
default:
}
// get time we should wait before attempting to connect again
- dur := boff.Duration()
- rtm.Debugf("reconnection %d failed: %s", boff.attempts+1, err)
- rtm.Debugln(" -> reconnecting in", dur)
- time.Sleep(dur)
+ rtm.Debugf("reconnection %d failed: %s reconnecting in %v\n", boff.attempts, err, backoff)
+ time.Sleep(backoff)
}
}
@@ -157,6 +176,14 @@ func (rtm *RTM) startRTMAndDial(useRTMStart bool) (info *Info, _ *websocket.Conn
return nil, nil, err
}
+ // install connection parameters
+ u, err := stdurl.Parse(url)
+ if err != nil {
+ return nil, nil, err
+ }
+ u.RawQuery = rtm.connParams.Encode()
+ url = u.String()
+
rtm.Debugf("Dialing to websocket on url %s", url)
// Only use HTTPS for connections to prevent MITM attacks on the connection.
upgradeHeader := http.Header{}
@@ -178,15 +205,19 @@ func (rtm *RTM) startRTMAndDial(useRTMStart bool) (info *Info, _ *websocket.Conn
//
// This should not be called directly! Instead a boolean value (true for
// intentional, false otherwise) should be sent to the killChannel on the RTM.
-func (rtm *RTM) killConnection(keepRunning chan bool, intentional bool) error {
+func (rtm *RTM) killConnection(intentional bool) (err error) {
rtm.Debugln("killing connection")
- if rtm.isConnected {
- close(keepRunning)
+
+ if rtm.conn != nil {
+ err = rtm.conn.Close()
}
- rtm.isConnected = false
- rtm.wasIntentional = intentional
- err := rtm.conn.Close()
+
rtm.IncomingEvents <- RTMEvent{"disconnected", &DisconnectedEvent{intentional}}
+
+ if intentional {
+ rtm.disconnect()
+ }
+
return err
}
@@ -195,31 +226,29 @@ func (rtm *RTM) killConnection(keepRunning chan bool, intentional bool) error {
// interval. This also sends outgoing messages that are received from the RTM's
// outgoingMessages channel. This also handles incoming raw events from the RTM
// rawEvents channel.
-func (rtm *RTM) handleEvents(keepRunning chan bool) {
+func (rtm *RTM) handleEvents() {
ticker := time.NewTicker(rtm.pingInterval)
defer ticker.Stop()
for {
select {
// catch "stop" signal on channel close
case intentional := <-rtm.killChannel:
- _ = rtm.killConnection(keepRunning, intentional)
+ _ = rtm.killConnection(intentional)
return
-
// detect when the connection is dead.
case <-rtm.pingDeadman.C:
rtm.Debugln("deadman switch trigger disconnecting")
- _ = rtm.killConnection(keepRunning, false)
+ _ = rtm.killConnection(false)
+ return
// send pings on ticker interval
case <-ticker.C:
- err := rtm.ping()
- if err != nil {
- _ = rtm.killConnection(keepRunning, false)
+ if err := rtm.ping(); err != nil {
+ _ = rtm.killConnection(false)
return
}
case <-rtm.forcePing:
- err := rtm.ping()
- if err != nil {
- _ = rtm.killConnection(keepRunning, false)
+ if err := rtm.ping(); err != nil {
+ _ = rtm.killConnection(false)
return
}
// listen for messages that need to be sent
@@ -229,7 +258,8 @@ func (rtm *RTM) handleEvents(keepRunning chan bool) {
case rawEvent := <-rtm.rawEvents:
switch rtm.handleRawEvent(rawEvent) {
case rtmEventTypeGoodbye:
- _ = rtm.killConnection(keepRunning, false)
+ _ = rtm.killConnection(false)
+ return
default:
}
}
@@ -241,17 +271,10 @@ func (rtm *RTM) handleEvents(keepRunning chan bool) {
//
// This will stop executing once the RTM's keepRunning channel has been closed
// or has anything sent to it.
-func (rtm *RTM) handleIncomingEvents(keepRunning <-chan bool) {
+func (rtm *RTM) handleIncomingEvents() {
for {
- // non-blocking listen to see if channel is closed
- select {
- // catch "stop" signal on channel close
- case <-keepRunning:
+ if err := rtm.receiveIncomingEvent(); err != nil {
return
- default:
- if err := rtm.receiveIncomingEvent(); err != nil {
- return
- }
}
}
}
@@ -274,7 +297,7 @@ func (rtm *RTM) sendWithDeadline(msg interface{}) error {
// and instead lets a future failed 'PING' detect the failed connection.
func (rtm *RTM) sendOutgoingMessage(msg OutgoingMessage) {
rtm.Debugln("Sending message:", msg)
- if len(msg.Text) > MaxMessageTextLength {
+ if len([]rune(msg.Text)) > MaxMessageTextLength {
rtm.IncomingEvents <- RTMEvent{"outgoing_error", &MessageTooLongEvent{
Message: msg,
MaxLength: MaxMessageTextLength,
@@ -323,20 +346,32 @@ func (rtm *RTM) receiveIncomingEvent() error {
// 'PING' message
// trigger a 'PING' to detect potential websocket disconnect
- rtm.forcePing <- true
+ select {
+ case rtm.forcePing <- true:
+ case <-rtm.disconnected:
+ }
case err != nil:
// All other errors from ReadJSON come from NextReader, and should
// kill the read loop and force a reconnect.
rtm.IncomingEvents <- RTMEvent{"incoming_error", &IncomingEventError{
ErrorObj: err,
}}
- rtm.killChannel <- false
+
+ select {
+ case rtm.killChannel <- false:
+ case <-rtm.disconnected:
+ }
+
return err
case len(event) == 0:
rtm.Debugln("Received empty event")
default:
- rtm.Debugln("Incoming Event:", string(event[:]))
- rtm.rawEvents <- event
+ rtm.Debugln("Incoming Event:", string(event))
+ select {
+ case rtm.rawEvents <- event:
+ case <-rtm.disconnected:
+ rtm.Debugln("disonnected while attempting to send raw event")
+ }
}
return nil
}
@@ -405,8 +440,7 @@ func (rtm *RTM) handlePong(event json.RawMessage) {
rtm.resetDeadman()
if err := json.Unmarshal(event, &p); err != nil {
- logger.Println("RTM Error unmarshalling 'pong' event:", err)
- rtm.Debugln(" -> Erroneous 'ping' event:", string(event))
+ rtm.Client.log.Println("RTM Error unmarshalling 'pong' event:", err)
return
}
@@ -423,8 +457,8 @@ func (rtm *RTM) handlePong(event json.RawMessage) {
func (rtm *RTM) handleEvent(typeStr string, event json.RawMessage) {
v, exists := EventMapping[typeStr]
if !exists {
- rtm.Debugf("RTM Error, received unmapped event %q: %s\n", typeStr, string(event))
- err := fmt.Errorf("RTM Error: Received unmapped event %q: %s\n", typeStr, string(event))
+ rtm.Debugf("RTM Error - received unmapped event %q: %s\n", typeStr, string(event))
+ err := fmt.Errorf("RTM Error: Received unmapped event %q: %s", typeStr, string(event))
rtm.IncomingEvents <- RTMEvent{"unmarshalling_error", &UnmarshallingErrorEvent{err}}
return
}
@@ -433,7 +467,7 @@ func (rtm *RTM) handleEvent(typeStr string, event json.RawMessage) {
err := json.Unmarshal(event, recvEvent)
if err != nil {
rtm.Debugf("RTM Error, could not unmarshall event %q: %s\n", typeStr, string(event))
- err := fmt.Errorf("RTM Error: Could not unmarshall event %q: %s\n", typeStr, string(event))
+ err := fmt.Errorf("RTM Error: Could not unmarshall event %q: %s", typeStr, string(event))
rtm.IncomingEvents <- RTMEvent{"unmarshalling_error", &UnmarshallingErrorEvent{err}}
return
}
diff --git a/vendor/github.com/nlopes/slack/websocket_misc.go b/vendor/github.com/nlopes/slack/websocket_misc.go
index 16f48c748..bfcc805e6 100644
--- a/vendor/github.com/nlopes/slack/websocket_misc.go
+++ b/vendor/github.com/nlopes/slack/websocket_misc.go
@@ -43,9 +43,10 @@ type HelloEvent struct{}
// PresenceChangeEvent represents the presence change event
type PresenceChangeEvent struct {
- Type string `json:"type"`
- Presence string `json:"presence"`
- User string `json:"user"`
+ Type string `json:"type"`
+ Presence string `json:"presence"`
+ User string `json:"user"`
+ Users []string `json:"users"`
}
// UserTypingEvent represents the user typing event
diff --git a/vendor/github.com/pmezard/go-difflib/LICENSE b/vendor/github.com/pmezard/go-difflib/LICENSE
new file mode 100644
index 000000000..c67dad612
--- /dev/null
+++ b/vendor/github.com/pmezard/go-difflib/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2013, Patrick Mezard
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+ The names of its contributors may not be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/pmezard/go-difflib/difflib/difflib.go b/vendor/github.com/pmezard/go-difflib/difflib/difflib.go
new file mode 100644
index 000000000..003e99fad
--- /dev/null
+++ b/vendor/github.com/pmezard/go-difflib/difflib/difflib.go
@@ -0,0 +1,772 @@
+// Package difflib is a partial port of Python difflib module.
+//
+// It provides tools to compare sequences of strings and generate textual diffs.
+//
+// The following class and functions have been ported:
+//
+// - SequenceMatcher
+//
+// - unified_diff
+//
+// - context_diff
+//
+// Getting unified diffs was the main goal of the port. Keep in mind this code
+// is mostly suitable to output text differences in a human friendly way, there
+// are no guarantees generated diffs are consumable by patch(1).
+package difflib
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "io"
+ "strings"
+)
+
+func min(a, b int) int {
+ if a < b {
+ return a
+ }
+ return b
+}
+
+func max(a, b int) int {
+ if a > b {
+ return a
+ }
+ return b
+}
+
+func calculateRatio(matches, length int) float64 {
+ if length > 0 {
+ return 2.0 * float64(matches) / float64(length)
+ }
+ return 1.0
+}
+
+type Match struct {
+ A int
+ B int
+ Size int
+}
+
+type OpCode struct {
+ Tag byte
+ I1 int
+ I2 int
+ J1 int
+ J2 int
+}
+
+// SequenceMatcher compares sequence of strings. The basic
+// algorithm predates, and is a little fancier than, an algorithm
+// published in the late 1980's by Ratcliff and Obershelp under the
+// hyperbolic name "gestalt pattern matching". The basic idea is to find
+// the longest contiguous matching subsequence that contains no "junk"
+// elements (R-O doesn't address junk). The same idea is then applied
+// recursively to the pieces of the sequences to the left and to the right
+// of the matching subsequence. This does not yield minimal edit
+// sequences, but does tend to yield matches that "look right" to people.
+//
+// SequenceMatcher tries to compute a "human-friendly diff" between two
+// sequences. Unlike e.g. UNIX(tm) diff, the fundamental notion is the
+// longest *contiguous* & junk-free matching subsequence. That's what
+// catches peoples' eyes. The Windows(tm) windiff has another interesting
+// notion, pairing up elements that appear uniquely in each sequence.
+// That, and the method here, appear to yield more intuitive difference
+// reports than does diff. This method appears to be the least vulnerable
+// to synching up on blocks of "junk lines", though (like blank lines in
+// ordinary text files, or maybe "" lines in HTML files). That may be
+// because this is the only method of the 3 that has a *concept* of
+// "junk" .
+//
+// Timing: Basic R-O is cubic time worst case and quadratic time expected
+// case. SequenceMatcher is quadratic time for the worst case and has
+// expected-case behavior dependent in a complicated way on how many
+// elements the sequences have in common; best case time is linear.
+type SequenceMatcher struct {
+ a []string
+ b []string
+ b2j map[string][]int
+ IsJunk func(string) bool
+ autoJunk bool
+ bJunk map[string]struct{}
+ matchingBlocks []Match
+ fullBCount map[string]int
+ bPopular map[string]struct{}
+ opCodes []OpCode
+}
+
+func NewMatcher(a, b []string) *SequenceMatcher {
+ m := SequenceMatcher{autoJunk: true}
+ m.SetSeqs(a, b)
+ return &m
+}
+
+func NewMatcherWithJunk(a, b []string, autoJunk bool,
+ isJunk func(string) bool) *SequenceMatcher {
+
+ m := SequenceMatcher{IsJunk: isJunk, autoJunk: autoJunk}
+ m.SetSeqs(a, b)
+ return &m
+}
+
+// Set two sequences to be compared.
+func (m *SequenceMatcher) SetSeqs(a, b []string) {
+ m.SetSeq1(a)
+ m.SetSeq2(b)
+}
+
+// Set the first sequence to be compared. The second sequence to be compared is
+// not changed.
+//
+// SequenceMatcher computes and caches detailed information about the second
+// sequence, so if you want to compare one sequence S against many sequences,
+// use .SetSeq2(s) once and call .SetSeq1(x) repeatedly for each of the other
+// sequences.
+//
+// See also SetSeqs() and SetSeq2().
+func (m *SequenceMatcher) SetSeq1(a []string) {
+ if &a == &m.a {
+ return
+ }
+ m.a = a
+ m.matchingBlocks = nil
+ m.opCodes = nil
+}
+
+// Set the second sequence to be compared. The first sequence to be compared is
+// not changed.
+func (m *SequenceMatcher) SetSeq2(b []string) {
+ if &b == &m.b {
+ return
+ }
+ m.b = b
+ m.matchingBlocks = nil
+ m.opCodes = nil
+ m.fullBCount = nil
+ m.chainB()
+}
+
+func (m *SequenceMatcher) chainB() {
+ // Populate line -> index mapping
+ b2j := map[string][]int{}
+ for i, s := range m.b {
+ indices := b2j[s]
+ indices = append(indices, i)
+ b2j[s] = indices
+ }
+
+ // Purge junk elements
+ m.bJunk = map[string]struct{}{}
+ if m.IsJunk != nil {
+ junk := m.bJunk
+ for s, _ := range b2j {
+ if m.IsJunk(s) {
+ junk[s] = struct{}{}
+ }
+ }
+ for s, _ := range junk {
+ delete(b2j, s)
+ }
+ }
+
+ // Purge remaining popular elements
+ popular := map[string]struct{}{}
+ n := len(m.b)
+ if m.autoJunk && n >= 200 {
+ ntest := n/100 + 1
+ for s, indices := range b2j {
+ if len(indices) > ntest {
+ popular[s] = struct{}{}
+ }
+ }
+ for s, _ := range popular {
+ delete(b2j, s)
+ }
+ }
+ m.bPopular = popular
+ m.b2j = b2j
+}
+
+func (m *SequenceMatcher) isBJunk(s string) bool {
+ _, ok := m.bJunk[s]
+ return ok
+}
+
+// Find longest matching block in a[alo:ahi] and b[blo:bhi].
+//
+// If IsJunk is not defined:
+//
+// Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where
+// alo <= i <= i+k <= ahi
+// blo <= j <= j+k <= bhi
+// and for all (i',j',k') meeting those conditions,
+// k >= k'
+// i <= i'
+// and if i == i', j <= j'
+//
+// In other words, of all maximal matching blocks, return one that
+// starts earliest in a, and of all those maximal matching blocks that
+// start earliest in a, return the one that starts earliest in b.
+//
+// If IsJunk is defined, first the longest matching block is
+// determined as above, but with the additional restriction that no
+// junk element appears in the block. Then that block is extended as
+// far as possible by matching (only) junk elements on both sides. So
+// the resulting block never matches on junk except as identical junk
+// happens to be adjacent to an "interesting" match.
+//
+// If no blocks match, return (alo, blo, 0).
+func (m *SequenceMatcher) findLongestMatch(alo, ahi, blo, bhi int) Match {
+ // CAUTION: stripping common prefix or suffix would be incorrect.
+ // E.g.,
+ // ab
+ // acab
+ // Longest matching block is "ab", but if common prefix is
+ // stripped, it's "a" (tied with "b"). UNIX(tm) diff does so
+ // strip, so ends up claiming that ab is changed to acab by
+ // inserting "ca" in the middle. That's minimal but unintuitive:
+ // "it's obvious" that someone inserted "ac" at the front.
+ // Windiff ends up at the same place as diff, but by pairing up
+ // the unique 'b's and then matching the first two 'a's.
+ besti, bestj, bestsize := alo, blo, 0
+
+ // find longest junk-free match
+ // during an iteration of the loop, j2len[j] = length of longest
+ // junk-free match ending with a[i-1] and b[j]
+ j2len := map[int]int{}
+ for i := alo; i != ahi; i++ {
+ // look at all instances of a[i] in b; note that because
+ // b2j has no junk keys, the loop is skipped if a[i] is junk
+ newj2len := map[int]int{}
+ for _, j := range m.b2j[m.a[i]] {
+ // a[i] matches b[j]
+ if j < blo {
+ continue
+ }
+ if j >= bhi {
+ break
+ }
+ k := j2len[j-1] + 1
+ newj2len[j] = k
+ if k > bestsize {
+ besti, bestj, bestsize = i-k+1, j-k+1, k
+ }
+ }
+ j2len = newj2len
+ }
+
+ // Extend the best by non-junk elements on each end. In particular,
+ // "popular" non-junk elements aren't in b2j, which greatly speeds
+ // the inner loop above, but also means "the best" match so far
+ // doesn't contain any junk *or* popular non-junk elements.
+ for besti > alo && bestj > blo && !m.isBJunk(m.b[bestj-1]) &&
+ m.a[besti-1] == m.b[bestj-1] {
+ besti, bestj, bestsize = besti-1, bestj-1, bestsize+1
+ }
+ for besti+bestsize < ahi && bestj+bestsize < bhi &&
+ !m.isBJunk(m.b[bestj+bestsize]) &&
+ m.a[besti+bestsize] == m.b[bestj+bestsize] {
+ bestsize += 1
+ }
+
+ // Now that we have a wholly interesting match (albeit possibly
+ // empty!), we may as well suck up the matching junk on each
+ // side of it too. Can't think of a good reason not to, and it
+ // saves post-processing the (possibly considerable) expense of
+ // figuring out what to do with it. In the case of an empty
+ // interesting match, this is clearly the right thing to do,
+ // because no other kind of match is possible in the regions.
+ for besti > alo && bestj > blo && m.isBJunk(m.b[bestj-1]) &&
+ m.a[besti-1] == m.b[bestj-1] {
+ besti, bestj, bestsize = besti-1, bestj-1, bestsize+1
+ }
+ for besti+bestsize < ahi && bestj+bestsize < bhi &&
+ m.isBJunk(m.b[bestj+bestsize]) &&
+ m.a[besti+bestsize] == m.b[bestj+bestsize] {
+ bestsize += 1
+ }
+
+ return Match{A: besti, B: bestj, Size: bestsize}
+}
+
+// Return list of triples describing matching subsequences.
+//
+// Each triple is of the form (i, j, n), and means that
+// a[i:i+n] == b[j:j+n]. The triples are monotonically increasing in
+// i and in j. It's also guaranteed that if (i, j, n) and (i', j', n') are
+// adjacent triples in the list, and the second is not the last triple in the
+// list, then i+n != i' or j+n != j'. IOW, adjacent triples never describe
+// adjacent equal blocks.
+//
+// The last triple is a dummy, (len(a), len(b), 0), and is the only
+// triple with n==0.
+func (m *SequenceMatcher) GetMatchingBlocks() []Match {
+ if m.matchingBlocks != nil {
+ return m.matchingBlocks
+ }
+
+ var matchBlocks func(alo, ahi, blo, bhi int, matched []Match) []Match
+ matchBlocks = func(alo, ahi, blo, bhi int, matched []Match) []Match {
+ match := m.findLongestMatch(alo, ahi, blo, bhi)
+ i, j, k := match.A, match.B, match.Size
+ if match.Size > 0 {
+ if alo < i && blo < j {
+ matched = matchBlocks(alo, i, blo, j, matched)
+ }
+ matched = append(matched, match)
+ if i+k < ahi && j+k < bhi {
+ matched = matchBlocks(i+k, ahi, j+k, bhi, matched)
+ }
+ }
+ return matched
+ }
+ matched := matchBlocks(0, len(m.a), 0, len(m.b), nil)
+
+ // It's possible that we have adjacent equal blocks in the
+ // matching_blocks list now.
+ nonAdjacent := []Match{}
+ i1, j1, k1 := 0, 0, 0
+ for _, b := range matched {
+ // Is this block adjacent to i1, j1, k1?
+ i2, j2, k2 := b.A, b.B, b.Size
+ if i1+k1 == i2 && j1+k1 == j2 {
+ // Yes, so collapse them -- this just increases the length of
+ // the first block by the length of the second, and the first
+ // block so lengthened remains the block to compare against.
+ k1 += k2
+ } else {
+ // Not adjacent. Remember the first block (k1==0 means it's
+ // the dummy we started with), and make the second block the
+ // new block to compare against.
+ if k1 > 0 {
+ nonAdjacent = append(nonAdjacent, Match{i1, j1, k1})
+ }
+ i1, j1, k1 = i2, j2, k2
+ }
+ }
+ if k1 > 0 {
+ nonAdjacent = append(nonAdjacent, Match{i1, j1, k1})
+ }
+
+ nonAdjacent = append(nonAdjacent, Match{len(m.a), len(m.b), 0})
+ m.matchingBlocks = nonAdjacent
+ return m.matchingBlocks
+}
+
+// Return list of 5-tuples describing how to turn a into b.
+//
+// Each tuple is of the form (tag, i1, i2, j1, j2). The first tuple
+// has i1 == j1 == 0, and remaining tuples have i1 == the i2 from the
+// tuple preceding it, and likewise for j1 == the previous j2.
+//
+// The tags are characters, with these meanings:
+//
+// 'r' (replace): a[i1:i2] should be replaced by b[j1:j2]
+//
+// 'd' (delete): a[i1:i2] should be deleted, j1==j2 in this case.
+//
+// 'i' (insert): b[j1:j2] should be inserted at a[i1:i1], i1==i2 in this case.
+//
+// 'e' (equal): a[i1:i2] == b[j1:j2]
+func (m *SequenceMatcher) GetOpCodes() []OpCode {
+ if m.opCodes != nil {
+ return m.opCodes
+ }
+ i, j := 0, 0
+ matching := m.GetMatchingBlocks()
+ opCodes := make([]OpCode, 0, len(matching))
+ for _, m := range matching {
+ // invariant: we've pumped out correct diffs to change
+ // a[:i] into b[:j], and the next matching block is
+ // a[ai:ai+size] == b[bj:bj+size]. So we need to pump
+ // out a diff to change a[i:ai] into b[j:bj], pump out
+ // the matching block, and move (i,j) beyond the match
+ ai, bj, size := m.A, m.B, m.Size
+ tag := byte(0)
+ if i < ai && j < bj {
+ tag = 'r'
+ } else if i < ai {
+ tag = 'd'
+ } else if j < bj {
+ tag = 'i'
+ }
+ if tag > 0 {
+ opCodes = append(opCodes, OpCode{tag, i, ai, j, bj})
+ }
+ i, j = ai+size, bj+size
+ // the list of matching blocks is terminated by a
+ // sentinel with size 0
+ if size > 0 {
+ opCodes = append(opCodes, OpCode{'e', ai, i, bj, j})
+ }
+ }
+ m.opCodes = opCodes
+ return m.opCodes
+}
+
+// Isolate change clusters by eliminating ranges with no changes.
+//
+// Return a generator of groups with up to n lines of context.
+// Each group is in the same format as returned by GetOpCodes().
+func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode {
+ if n < 0 {
+ n = 3
+ }
+ codes := m.GetOpCodes()
+ if len(codes) == 0 {
+ codes = []OpCode{OpCode{'e', 0, 1, 0, 1}}
+ }
+ // Fixup leading and trailing groups if they show no changes.
+ if codes[0].Tag == 'e' {
+ c := codes[0]
+ i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2
+ codes[0] = OpCode{c.Tag, max(i1, i2-n), i2, max(j1, j2-n), j2}
+ }
+ if codes[len(codes)-1].Tag == 'e' {
+ c := codes[len(codes)-1]
+ i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2
+ codes[len(codes)-1] = OpCode{c.Tag, i1, min(i2, i1+n), j1, min(j2, j1+n)}
+ }
+ nn := n + n
+ groups := [][]OpCode{}
+ group := []OpCode{}
+ for _, c := range codes {
+ i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2
+ // End the current group and start a new one whenever
+ // there is a large range with no changes.
+ if c.Tag == 'e' && i2-i1 > nn {
+ group = append(group, OpCode{c.Tag, i1, min(i2, i1+n),
+ j1, min(j2, j1+n)})
+ groups = append(groups, group)
+ group = []OpCode{}
+ i1, j1 = max(i1, i2-n), max(j1, j2-n)
+ }
+ group = append(group, OpCode{c.Tag, i1, i2, j1, j2})
+ }
+ if len(group) > 0 && !(len(group) == 1 && group[0].Tag == 'e') {
+ groups = append(groups, group)
+ }
+ return groups
+}
+
+// Return a measure of the sequences' similarity (float in [0,1]).
+//
+// Where T is the total number of elements in both sequences, and
+// M is the number of matches, this is 2.0*M / T.
+// Note that this is 1 if the sequences are identical, and 0 if
+// they have nothing in common.
+//
+// .Ratio() is expensive to compute if you haven't already computed
+// .GetMatchingBlocks() or .GetOpCodes(), in which case you may
+// want to try .QuickRatio() or .RealQuickRation() first to get an
+// upper bound.
+func (m *SequenceMatcher) Ratio() float64 {
+ matches := 0
+ for _, m := range m.GetMatchingBlocks() {
+ matches += m.Size
+ }
+ return calculateRatio(matches, len(m.a)+len(m.b))
+}
+
+// Return an upper bound on ratio() relatively quickly.
+//
+// This isn't defined beyond that it is an upper bound on .Ratio(), and
+// is faster to compute.
+func (m *SequenceMatcher) QuickRatio() float64 {
+ // viewing a and b as multisets, set matches to the cardinality
+ // of their intersection; this counts the number of matches
+ // without regard to order, so is clearly an upper bound
+ if m.fullBCount == nil {
+ m.fullBCount = map[string]int{}
+ for _, s := range m.b {
+ m.fullBCount[s] = m.fullBCount[s] + 1
+ }
+ }
+
+ // avail[x] is the number of times x appears in 'b' less the
+ // number of times we've seen it in 'a' so far ... kinda
+ avail := map[string]int{}
+ matches := 0
+ for _, s := range m.a {
+ n, ok := avail[s]
+ if !ok {
+ n = m.fullBCount[s]
+ }
+ avail[s] = n - 1
+ if n > 0 {
+ matches += 1
+ }
+ }
+ return calculateRatio(matches, len(m.a)+len(m.b))
+}
+
+// Return an upper bound on ratio() very quickly.
+//
+// This isn't defined beyond that it is an upper bound on .Ratio(), and
+// is faster to compute than either .Ratio() or .QuickRatio().
+func (m *SequenceMatcher) RealQuickRatio() float64 {
+ la, lb := len(m.a), len(m.b)
+ return calculateRatio(min(la, lb), la+lb)
+}
+
+// Convert range to the "ed" format
+func formatRangeUnified(start, stop int) string {
+ // Per the diff spec at http://www.unix.org/single_unix_specification/
+ beginning := start + 1 // lines start numbering with one
+ length := stop - start
+ if length == 1 {
+ return fmt.Sprintf("%d", beginning)
+ }
+ if length == 0 {
+ beginning -= 1 // empty ranges begin at line just before the range
+ }
+ return fmt.Sprintf("%d,%d", beginning, length)
+}
+
+// Unified diff parameters
+type UnifiedDiff struct {
+ A []string // First sequence lines
+ FromFile string // First file name
+ FromDate string // First file time
+ B []string // Second sequence lines
+ ToFile string // Second file name
+ ToDate string // Second file time
+ Eol string // Headers end of line, defaults to LF
+ Context int // Number of context lines
+}
+
+// Compare two sequences of lines; generate the delta as a unified diff.
+//
+// Unified diffs are a compact way of showing line changes and a few
+// lines of context. The number of context lines is set by 'n' which
+// defaults to three.
+//
+// By default, the diff control lines (those with ---, +++, or @@) are
+// created with a trailing newline. This is helpful so that inputs
+// created from file.readlines() result in diffs that are suitable for
+// file.writelines() since both the inputs and outputs have trailing
+// newlines.
+//
+// For inputs that do not have trailing newlines, set the lineterm
+// argument to "" so that the output will be uniformly newline free.
+//
+// The unidiff format normally has a header for filenames and modification
+// times. Any or all of these may be specified using strings for
+// 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'.
+// The modification times are normally expressed in the ISO 8601 format.
+func WriteUnifiedDiff(writer io.Writer, diff UnifiedDiff) error {
+ buf := bufio.NewWriter(writer)
+ defer buf.Flush()
+ wf := func(format string, args ...interface{}) error {
+ _, err := buf.WriteString(fmt.Sprintf(format, args...))
+ return err
+ }
+ ws := func(s string) error {
+ _, err := buf.WriteString(s)
+ return err
+ }
+
+ if len(diff.Eol) == 0 {
+ diff.Eol = "\n"
+ }
+
+ started := false
+ m := NewMatcher(diff.A, diff.B)
+ for _, g := range m.GetGroupedOpCodes(diff.Context) {
+ if !started {
+ started = true
+ fromDate := ""
+ if len(diff.FromDate) > 0 {
+ fromDate = "\t" + diff.FromDate
+ }
+ toDate := ""
+ if len(diff.ToDate) > 0 {
+ toDate = "\t" + diff.ToDate
+ }
+ if diff.FromFile != "" || diff.ToFile != "" {
+ err := wf("--- %s%s%s", diff.FromFile, fromDate, diff.Eol)
+ if err != nil {
+ return err
+ }
+ err = wf("+++ %s%s%s", diff.ToFile, toDate, diff.Eol)
+ if err != nil {
+ return err
+ }
+ }
+ }
+ first, last := g[0], g[len(g)-1]
+ range1 := formatRangeUnified(first.I1, last.I2)
+ range2 := formatRangeUnified(first.J1, last.J2)
+ if err := wf("@@ -%s +%s @@%s", range1, range2, diff.Eol); err != nil {
+ return err
+ }
+ for _, c := range g {
+ i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2
+ if c.Tag == 'e' {
+ for _, line := range diff.A[i1:i2] {
+ if err := ws(" " + line); err != nil {
+ return err
+ }
+ }
+ continue
+ }
+ if c.Tag == 'r' || c.Tag == 'd' {
+ for _, line := range diff.A[i1:i2] {
+ if err := ws("-" + line); err != nil {
+ return err
+ }
+ }
+ }
+ if c.Tag == 'r' || c.Tag == 'i' {
+ for _, line := range diff.B[j1:j2] {
+ if err := ws("+" + line); err != nil {
+ return err
+ }
+ }
+ }
+ }
+ }
+ return nil
+}
+
+// Like WriteUnifiedDiff but returns the diff a string.
+func GetUnifiedDiffString(diff UnifiedDiff) (string, error) {
+ w := &bytes.Buffer{}
+ err := WriteUnifiedDiff(w, diff)
+ return string(w.Bytes()), err
+}
+
+// Convert range to the "ed" format.
+func formatRangeContext(start, stop int) string {
+ // Per the diff spec at http://www.unix.org/single_unix_specification/
+ beginning := start + 1 // lines start numbering with one
+ length := stop - start
+ if length == 0 {
+ beginning -= 1 // empty ranges begin at line just before the range
+ }
+ if length <= 1 {
+ return fmt.Sprintf("%d", beginning)
+ }
+ return fmt.Sprintf("%d,%d", beginning, beginning+length-1)
+}
+
+type ContextDiff UnifiedDiff
+
+// Compare two sequences of lines; generate the delta as a context diff.
+//
+// Context diffs are a compact way of showing line changes and a few
+// lines of context. The number of context lines is set by diff.Context
+// which defaults to three.
+//
+// By default, the diff control lines (those with *** or ---) are
+// created with a trailing newline.
+//
+// For inputs that do not have trailing newlines, set the diff.Eol
+// argument to "" so that the output will be uniformly newline free.
+//
+// The context diff format normally has a header for filenames and
+// modification times. Any or all of these may be specified using
+// strings for diff.FromFile, diff.ToFile, diff.FromDate, diff.ToDate.
+// The modification times are normally expressed in the ISO 8601 format.
+// If not specified, the strings default to blanks.
+func WriteContextDiff(writer io.Writer, diff ContextDiff) error {
+ buf := bufio.NewWriter(writer)
+ defer buf.Flush()
+ var diffErr error
+ wf := func(format string, args ...interface{}) {
+ _, err := buf.WriteString(fmt.Sprintf(format, args...))
+ if diffErr == nil && err != nil {
+ diffErr = err
+ }
+ }
+ ws := func(s string) {
+ _, err := buf.WriteString(s)
+ if diffErr == nil && err != nil {
+ diffErr = err
+ }
+ }
+
+ if len(diff.Eol) == 0 {
+ diff.Eol = "\n"
+ }
+
+ prefix := map[byte]string{
+ 'i': "+ ",
+ 'd': "- ",
+ 'r': "! ",
+ 'e': " ",
+ }
+
+ started := false
+ m := NewMatcher(diff.A, diff.B)
+ for _, g := range m.GetGroupedOpCodes(diff.Context) {
+ if !started {
+ started = true
+ fromDate := ""
+ if len(diff.FromDate) > 0 {
+ fromDate = "\t" + diff.FromDate
+ }
+ toDate := ""
+ if len(diff.ToDate) > 0 {
+ toDate = "\t" + diff.ToDate
+ }
+ if diff.FromFile != "" || diff.ToFile != "" {
+ wf("*** %s%s%s", diff.FromFile, fromDate, diff.Eol)
+ wf("--- %s%s%s", diff.ToFile, toDate, diff.Eol)
+ }
+ }
+
+ first, last := g[0], g[len(g)-1]
+ ws("***************" + diff.Eol)
+
+ range1 := formatRangeContext(first.I1, last.I2)
+ wf("*** %s ****%s", range1, diff.Eol)
+ for _, c := range g {
+ if c.Tag == 'r' || c.Tag == 'd' {
+ for _, cc := range g {
+ if cc.Tag == 'i' {
+ continue
+ }
+ for _, line := range diff.A[cc.I1:cc.I2] {
+ ws(prefix[cc.Tag] + line)
+ }
+ }
+ break
+ }
+ }
+
+ range2 := formatRangeContext(first.J1, last.J2)
+ wf("--- %s ----%s", range2, diff.Eol)
+ for _, c := range g {
+ if c.Tag == 'r' || c.Tag == 'i' {
+ for _, cc := range g {
+ if cc.Tag == 'd' {
+ continue
+ }
+ for _, line := range diff.B[cc.J1:cc.J2] {
+ ws(prefix[cc.Tag] + line)
+ }
+ }
+ break
+ }
+ }
+ }
+ return diffErr
+}
+
+// Like WriteContextDiff but returns the diff a string.
+func GetContextDiffString(diff ContextDiff) (string, error) {
+ w := &bytes.Buffer{}
+ err := WriteContextDiff(w, diff)
+ return string(w.Bytes()), err
+}
+
+// Split a string on "\n" while preserving them. The output can be used
+// as input for UnifiedDiff and ContextDiff structures.
+func SplitLines(s string) []string {
+ lines := strings.SplitAfter(s, "\n")
+ lines[len(lines)-1] += "\n"
+ return lines
+}
diff --git a/vendor/github.com/stretchr/testify/LICENSE b/vendor/github.com/stretchr/testify/LICENSE
new file mode 100644
index 000000000..f38ec5956
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2012-2018 Mat Ryer and Tyler Bunnell
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go b/vendor/github.com/stretchr/testify/assert/assertion_format.go
new file mode 100644
index 000000000..aa1c2b95c
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go
@@ -0,0 +1,484 @@
+/*
+* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
+* THIS FILE MUST NOT BE EDITED BY HAND
+ */
+
+package assert
+
+import (
+ http "net/http"
+ url "net/url"
+ time "time"
+)
+
+// Conditionf uses a Comparison to assert a complex condition.
+func Conditionf(t TestingT, comp Comparison, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Condition(t, comp, append([]interface{}{msg}, args...)...)
+}
+
+// Containsf asserts that the specified string, list(array, slice...) or map contains the
+// specified substring or element.
+//
+// assert.Containsf(t, "Hello World", "World", "error message %s", "formatted")
+// assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted")
+// assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted")
+func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Contains(t, s, contains, append([]interface{}{msg}, args...)...)
+}
+
+// DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists.
+func DirExistsf(t TestingT, path string, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return DirExists(t, path, append([]interface{}{msg}, args...)...)
+}
+
+// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified
+// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
+// the number of appearances of each of them in both lists should match.
+//
+// assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted")
+func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return ElementsMatch(t, listA, listB, append([]interface{}{msg}, args...)...)
+}
+
+// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// assert.Emptyf(t, obj, "error message %s", "formatted")
+func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Empty(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// Equalf asserts that two objects are equal.
+//
+// assert.Equalf(t, 123, 123, "error message %s", "formatted")
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses). Function equality
+// cannot be determined and will always fail.
+func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Equal(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// EqualErrorf asserts that a function returned an error (i.e. not `nil`)
+// and that it is equal to the provided error.
+//
+// actualObj, err := SomeFunction()
+// assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted")
+func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return EqualError(t, theError, errString, append([]interface{}{msg}, args...)...)
+}
+
+// EqualValuesf asserts that two objects are equal or convertable to the same types
+// and equal.
+//
+// assert.EqualValuesf(t, uint32(123, "error message %s", "formatted"), int32(123))
+func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return EqualValues(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// Errorf asserts that a function returned an error (i.e. not `nil`).
+//
+// actualObj, err := SomeFunction()
+// if assert.Errorf(t, err, "error message %s", "formatted") {
+// assert.Equal(t, expectedErrorf, err)
+// }
+func Errorf(t TestingT, err error, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Error(t, err, append([]interface{}{msg}, args...)...)
+}
+
+// Exactlyf asserts that two objects are equal in value and type.
+//
+// assert.Exactlyf(t, int32(123, "error message %s", "formatted"), int64(123))
+func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Exactly(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// Failf reports a failure through
+func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Fail(t, failureMessage, append([]interface{}{msg}, args...)...)
+}
+
+// FailNowf fails test
+func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return FailNow(t, failureMessage, append([]interface{}{msg}, args...)...)
+}
+
+// Falsef asserts that the specified value is false.
+//
+// assert.Falsef(t, myBool, "error message %s", "formatted")
+func Falsef(t TestingT, value bool, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return False(t, value, append([]interface{}{msg}, args...)...)
+}
+
+// FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file.
+func FileExistsf(t TestingT, path string, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return FileExists(t, path, append([]interface{}{msg}, args...)...)
+}
+
+// HTTPBodyContainsf asserts that a specified handler returns a
+// body that contains a string.
+//
+// assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPBodyContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...)
+}
+
+// HTTPBodyNotContainsf asserts that a specified handler returns a
+// body that does not contain a string.
+//
+// assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPBodyNotContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...)
+}
+
+// HTTPErrorf asserts that a specified handler returns an error status code.
+//
+// assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
+func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPError(t, handler, method, url, values, append([]interface{}{msg}, args...)...)
+}
+
+// HTTPRedirectf asserts that a specified handler returns a redirect status code.
+//
+// assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
+func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPRedirect(t, handler, method, url, values, append([]interface{}{msg}, args...)...)
+}
+
+// HTTPSuccessf asserts that a specified handler returns a success status code.
+//
+// assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPSuccess(t, handler, method, url, values, append([]interface{}{msg}, args...)...)
+}
+
+// Implementsf asserts that an object is implemented by the specified interface.
+//
+// assert.Implementsf(t, (*MyInterface, "error message %s", "formatted")(nil), new(MyObject))
+func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Implements(t, interfaceObject, object, append([]interface{}{msg}, args...)...)
+}
+
+// InDeltaf asserts that the two numerals are within delta of each other.
+//
+// assert.InDeltaf(t, math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01)
+func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return InDelta(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
+}
+
+// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
+func InDeltaMapValuesf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return InDeltaMapValues(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
+}
+
+// InDeltaSlicef is the same as InDelta, except it compares two slices.
+func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return InDeltaSlice(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
+}
+
+// InEpsilonf asserts that expected and actual have a relative error less than epsilon
+func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return InEpsilon(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...)
+}
+
+// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices.
+func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return InEpsilonSlice(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...)
+}
+
+// IsTypef asserts that the specified objects are of the same type.
+func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsType(t, expectedType, object, append([]interface{}{msg}, args...)...)
+}
+
+// JSONEqf asserts that two JSON strings are equivalent.
+//
+// assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted")
+func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return JSONEq(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// Lenf asserts that the specified object has specific length.
+// Lenf also fails if the object has a type that len() not accept.
+//
+// assert.Lenf(t, mySlice, 3, "error message %s", "formatted")
+func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Len(t, object, length, append([]interface{}{msg}, args...)...)
+}
+
+// Nilf asserts that the specified object is nil.
+//
+// assert.Nilf(t, err, "error message %s", "formatted")
+func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Nil(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// NoErrorf asserts that a function returned no error (i.e. `nil`).
+//
+// actualObj, err := SomeFunction()
+// if assert.NoErrorf(t, err, "error message %s", "formatted") {
+// assert.Equal(t, expectedObj, actualObj)
+// }
+func NoErrorf(t TestingT, err error, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NoError(t, err, append([]interface{}{msg}, args...)...)
+}
+
+// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the
+// specified substring or element.
+//
+// assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted")
+// assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted")
+// assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted")
+func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotContains(t, s, contains, append([]interface{}{msg}, args...)...)
+}
+
+// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// if assert.NotEmptyf(t, obj, "error message %s", "formatted") {
+// assert.Equal(t, "two", obj[1])
+// }
+func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotEmpty(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// NotEqualf asserts that the specified values are NOT equal.
+//
+// assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted")
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses).
+func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotEqual(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// NotNilf asserts that the specified object is not nil.
+//
+// assert.NotNilf(t, err, "error message %s", "formatted")
+func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotNil(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic.
+//
+// assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted")
+func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotPanics(t, f, append([]interface{}{msg}, args...)...)
+}
+
+// NotRegexpf asserts that a specified regexp does not match a string.
+//
+// assert.NotRegexpf(t, regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting")
+// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted")
+func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotRegexp(t, rx, str, append([]interface{}{msg}, args...)...)
+}
+
+// NotSubsetf asserts that the specified list(array, slice...) contains not all
+// elements given in the specified subset(array, slice...).
+//
+// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted")
+func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotSubset(t, list, subset, append([]interface{}{msg}, args...)...)
+}
+
+// NotZerof asserts that i is not the zero value for its type.
+func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotZero(t, i, append([]interface{}{msg}, args...)...)
+}
+
+// Panicsf asserts that the code inside the specified PanicTestFunc panics.
+//
+// assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted")
+func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Panics(t, f, append([]interface{}{msg}, args...)...)
+}
+
+// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that
+// the recovered panic value equals the expected panic value.
+//
+// assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
+func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return PanicsWithValue(t, expected, f, append([]interface{}{msg}, args...)...)
+}
+
+// Regexpf asserts that a specified regexp matches a string.
+//
+// assert.Regexpf(t, regexp.MustCompile("start", "error message %s", "formatted"), "it's starting")
+// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted")
+func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Regexp(t, rx, str, append([]interface{}{msg}, args...)...)
+}
+
+// Subsetf asserts that the specified list(array, slice...) contains all
+// elements given in the specified subset(array, slice...).
+//
+// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted")
+func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Subset(t, list, subset, append([]interface{}{msg}, args...)...)
+}
+
+// Truef asserts that the specified value is true.
+//
+// assert.Truef(t, myBool, "error message %s", "formatted")
+func Truef(t TestingT, value bool, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return True(t, value, append([]interface{}{msg}, args...)...)
+}
+
+// WithinDurationf asserts that the two times are within duration delta of each other.
+//
+// assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted")
+func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return WithinDuration(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
+}
+
+// Zerof asserts that i is the zero value for its type.
+func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Zero(t, i, append([]interface{}{msg}, args...)...)
+}
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl b/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl
new file mode 100644
index 000000000..d2bb0b817
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl
@@ -0,0 +1,5 @@
+{{.CommentFormat}}
+func {{.DocInfo.Name}}f(t TestingT, {{.ParamsFormat}}) bool {
+ if h, ok := t.(tHelper); ok { h.Helper() }
+ return {{.DocInfo.Name}}(t, {{.ForwardedParamsFormat}})
+}
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go b/vendor/github.com/stretchr/testify/assert/assertion_forward.go
new file mode 100644
index 000000000..de39f794e
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go
@@ -0,0 +1,956 @@
+/*
+* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
+* THIS FILE MUST NOT BE EDITED BY HAND
+ */
+
+package assert
+
+import (
+ http "net/http"
+ url "net/url"
+ time "time"
+)
+
+// Condition uses a Comparison to assert a complex condition.
+func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Condition(a.t, comp, msgAndArgs...)
+}
+
+// Conditionf uses a Comparison to assert a complex condition.
+func (a *Assertions) Conditionf(comp Comparison, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Conditionf(a.t, comp, msg, args...)
+}
+
+// Contains asserts that the specified string, list(array, slice...) or map contains the
+// specified substring or element.
+//
+// a.Contains("Hello World", "World")
+// a.Contains(["Hello", "World"], "World")
+// a.Contains({"Hello": "World"}, "Hello")
+func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Contains(a.t, s, contains, msgAndArgs...)
+}
+
+// Containsf asserts that the specified string, list(array, slice...) or map contains the
+// specified substring or element.
+//
+// a.Containsf("Hello World", "World", "error message %s", "formatted")
+// a.Containsf(["Hello", "World"], "World", "error message %s", "formatted")
+// a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted")
+func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Containsf(a.t, s, contains, msg, args...)
+}
+
+// DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists.
+func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return DirExists(a.t, path, msgAndArgs...)
+}
+
+// DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists.
+func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return DirExistsf(a.t, path, msg, args...)
+}
+
+// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified
+// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
+// the number of appearances of each of them in both lists should match.
+//
+// a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2])
+func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return ElementsMatch(a.t, listA, listB, msgAndArgs...)
+}
+
+// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified
+// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
+// the number of appearances of each of them in both lists should match.
+//
+// a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted")
+func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return ElementsMatchf(a.t, listA, listB, msg, args...)
+}
+
+// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// a.Empty(obj)
+func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Empty(a.t, object, msgAndArgs...)
+}
+
+// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// a.Emptyf(obj, "error message %s", "formatted")
+func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Emptyf(a.t, object, msg, args...)
+}
+
+// Equal asserts that two objects are equal.
+//
+// a.Equal(123, 123)
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses). Function equality
+// cannot be determined and will always fail.
+func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Equal(a.t, expected, actual, msgAndArgs...)
+}
+
+// EqualError asserts that a function returned an error (i.e. not `nil`)
+// and that it is equal to the provided error.
+//
+// actualObj, err := SomeFunction()
+// a.EqualError(err, expectedErrorString)
+func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return EqualError(a.t, theError, errString, msgAndArgs...)
+}
+
+// EqualErrorf asserts that a function returned an error (i.e. not `nil`)
+// and that it is equal to the provided error.
+//
+// actualObj, err := SomeFunction()
+// a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted")
+func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return EqualErrorf(a.t, theError, errString, msg, args...)
+}
+
+// EqualValues asserts that two objects are equal or convertable to the same types
+// and equal.
+//
+// a.EqualValues(uint32(123), int32(123))
+func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return EqualValues(a.t, expected, actual, msgAndArgs...)
+}
+
+// EqualValuesf asserts that two objects are equal or convertable to the same types
+// and equal.
+//
+// a.EqualValuesf(uint32(123, "error message %s", "formatted"), int32(123))
+func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return EqualValuesf(a.t, expected, actual, msg, args...)
+}
+
+// Equalf asserts that two objects are equal.
+//
+// a.Equalf(123, 123, "error message %s", "formatted")
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses). Function equality
+// cannot be determined and will always fail.
+func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Equalf(a.t, expected, actual, msg, args...)
+}
+
+// Error asserts that a function returned an error (i.e. not `nil`).
+//
+// actualObj, err := SomeFunction()
+// if a.Error(err) {
+// assert.Equal(t, expectedError, err)
+// }
+func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Error(a.t, err, msgAndArgs...)
+}
+
+// Errorf asserts that a function returned an error (i.e. not `nil`).
+//
+// actualObj, err := SomeFunction()
+// if a.Errorf(err, "error message %s", "formatted") {
+// assert.Equal(t, expectedErrorf, err)
+// }
+func (a *Assertions) Errorf(err error, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Errorf(a.t, err, msg, args...)
+}
+
+// Exactly asserts that two objects are equal in value and type.
+//
+// a.Exactly(int32(123), int64(123))
+func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Exactly(a.t, expected, actual, msgAndArgs...)
+}
+
+// Exactlyf asserts that two objects are equal in value and type.
+//
+// a.Exactlyf(int32(123, "error message %s", "formatted"), int64(123))
+func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Exactlyf(a.t, expected, actual, msg, args...)
+}
+
+// Fail reports a failure through
+func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Fail(a.t, failureMessage, msgAndArgs...)
+}
+
+// FailNow fails test
+func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return FailNow(a.t, failureMessage, msgAndArgs...)
+}
+
+// FailNowf fails test
+func (a *Assertions) FailNowf(failureMessage string, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return FailNowf(a.t, failureMessage, msg, args...)
+}
+
+// Failf reports a failure through
+func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Failf(a.t, failureMessage, msg, args...)
+}
+
+// False asserts that the specified value is false.
+//
+// a.False(myBool)
+func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return False(a.t, value, msgAndArgs...)
+}
+
+// Falsef asserts that the specified value is false.
+//
+// a.Falsef(myBool, "error message %s", "formatted")
+func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Falsef(a.t, value, msg, args...)
+}
+
+// FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file.
+func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return FileExists(a.t, path, msgAndArgs...)
+}
+
+// FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file.
+func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return FileExistsf(a.t, path, msg, args...)
+}
+
+// HTTPBodyContains asserts that a specified handler returns a
+// body that contains a string.
+//
+// a.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPBodyContains(a.t, handler, method, url, values, str, msgAndArgs...)
+}
+
+// HTTPBodyContainsf asserts that a specified handler returns a
+// body that contains a string.
+//
+// a.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPBodyContainsf(a.t, handler, method, url, values, str, msg, args...)
+}
+
+// HTTPBodyNotContains asserts that a specified handler returns a
+// body that does not contain a string.
+//
+// a.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPBodyNotContains(a.t, handler, method, url, values, str, msgAndArgs...)
+}
+
+// HTTPBodyNotContainsf asserts that a specified handler returns a
+// body that does not contain a string.
+//
+// a.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPBodyNotContainsf(a.t, handler, method, url, values, str, msg, args...)
+}
+
+// HTTPError asserts that a specified handler returns an error status code.
+//
+// a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPError(a.t, handler, method, url, values, msgAndArgs...)
+}
+
+// HTTPErrorf asserts that a specified handler returns an error status code.
+//
+// a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
+func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPErrorf(a.t, handler, method, url, values, msg, args...)
+}
+
+// HTTPRedirect asserts that a specified handler returns a redirect status code.
+//
+// a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPRedirect(a.t, handler, method, url, values, msgAndArgs...)
+}
+
+// HTTPRedirectf asserts that a specified handler returns a redirect status code.
+//
+// a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
+func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPRedirectf(a.t, handler, method, url, values, msg, args...)
+}
+
+// HTTPSuccess asserts that a specified handler returns a success status code.
+//
+// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPSuccess(a.t, handler, method, url, values, msgAndArgs...)
+}
+
+// HTTPSuccessf asserts that a specified handler returns a success status code.
+//
+// a.HTTPSuccessf(myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPSuccessf(a.t, handler, method, url, values, msg, args...)
+}
+
+// Implements asserts that an object is implemented by the specified interface.
+//
+// a.Implements((*MyInterface)(nil), new(MyObject))
+func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Implements(a.t, interfaceObject, object, msgAndArgs...)
+}
+
+// Implementsf asserts that an object is implemented by the specified interface.
+//
+// a.Implementsf((*MyInterface, "error message %s", "formatted")(nil), new(MyObject))
+func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Implementsf(a.t, interfaceObject, object, msg, args...)
+}
+
+// InDelta asserts that the two numerals are within delta of each other.
+//
+// a.InDelta(math.Pi, (22 / 7.0), 0.01)
+func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return InDelta(a.t, expected, actual, delta, msgAndArgs...)
+}
+
+// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
+func (a *Assertions) InDeltaMapValues(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return InDeltaMapValues(a.t, expected, actual, delta, msgAndArgs...)
+}
+
+// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
+func (a *Assertions) InDeltaMapValuesf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return InDeltaMapValuesf(a.t, expected, actual, delta, msg, args...)
+}
+
+// InDeltaSlice is the same as InDelta, except it compares two slices.
+func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...)
+}
+
+// InDeltaSlicef is the same as InDelta, except it compares two slices.
+func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return InDeltaSlicef(a.t, expected, actual, delta, msg, args...)
+}
+
+// InDeltaf asserts that the two numerals are within delta of each other.
+//
+// a.InDeltaf(math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01)
+func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return InDeltaf(a.t, expected, actual, delta, msg, args...)
+}
+
+// InEpsilon asserts that expected and actual have a relative error less than epsilon
+func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...)
+}
+
+// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices.
+func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...)
+}
+
+// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices.
+func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return InEpsilonSlicef(a.t, expected, actual, epsilon, msg, args...)
+}
+
+// InEpsilonf asserts that expected and actual have a relative error less than epsilon
+func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return InEpsilonf(a.t, expected, actual, epsilon, msg, args...)
+}
+
+// IsType asserts that the specified objects are of the same type.
+func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsType(a.t, expectedType, object, msgAndArgs...)
+}
+
+// IsTypef asserts that the specified objects are of the same type.
+func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsTypef(a.t, expectedType, object, msg, args...)
+}
+
+// JSONEq asserts that two JSON strings are equivalent.
+//
+// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
+func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return JSONEq(a.t, expected, actual, msgAndArgs...)
+}
+
+// JSONEqf asserts that two JSON strings are equivalent.
+//
+// a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted")
+func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return JSONEqf(a.t, expected, actual, msg, args...)
+}
+
+// Len asserts that the specified object has specific length.
+// Len also fails if the object has a type that len() not accept.
+//
+// a.Len(mySlice, 3)
+func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Len(a.t, object, length, msgAndArgs...)
+}
+
+// Lenf asserts that the specified object has specific length.
+// Lenf also fails if the object has a type that len() not accept.
+//
+// a.Lenf(mySlice, 3, "error message %s", "formatted")
+func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Lenf(a.t, object, length, msg, args...)
+}
+
+// Nil asserts that the specified object is nil.
+//
+// a.Nil(err)
+func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Nil(a.t, object, msgAndArgs...)
+}
+
+// Nilf asserts that the specified object is nil.
+//
+// a.Nilf(err, "error message %s", "formatted")
+func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Nilf(a.t, object, msg, args...)
+}
+
+// NoError asserts that a function returned no error (i.e. `nil`).
+//
+// actualObj, err := SomeFunction()
+// if a.NoError(err) {
+// assert.Equal(t, expectedObj, actualObj)
+// }
+func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NoError(a.t, err, msgAndArgs...)
+}
+
+// NoErrorf asserts that a function returned no error (i.e. `nil`).
+//
+// actualObj, err := SomeFunction()
+// if a.NoErrorf(err, "error message %s", "formatted") {
+// assert.Equal(t, expectedObj, actualObj)
+// }
+func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NoErrorf(a.t, err, msg, args...)
+}
+
+// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the
+// specified substring or element.
+//
+// a.NotContains("Hello World", "Earth")
+// a.NotContains(["Hello", "World"], "Earth")
+// a.NotContains({"Hello": "World"}, "Earth")
+func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotContains(a.t, s, contains, msgAndArgs...)
+}
+
+// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the
+// specified substring or element.
+//
+// a.NotContainsf("Hello World", "Earth", "error message %s", "formatted")
+// a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted")
+// a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted")
+func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotContainsf(a.t, s, contains, msg, args...)
+}
+
+// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// if a.NotEmpty(obj) {
+// assert.Equal(t, "two", obj[1])
+// }
+func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotEmpty(a.t, object, msgAndArgs...)
+}
+
+// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// if a.NotEmptyf(obj, "error message %s", "formatted") {
+// assert.Equal(t, "two", obj[1])
+// }
+func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotEmptyf(a.t, object, msg, args...)
+}
+
+// NotEqual asserts that the specified values are NOT equal.
+//
+// a.NotEqual(obj1, obj2)
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses).
+func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotEqual(a.t, expected, actual, msgAndArgs...)
+}
+
+// NotEqualf asserts that the specified values are NOT equal.
+//
+// a.NotEqualf(obj1, obj2, "error message %s", "formatted")
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses).
+func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotEqualf(a.t, expected, actual, msg, args...)
+}
+
+// NotNil asserts that the specified object is not nil.
+//
+// a.NotNil(err)
+func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotNil(a.t, object, msgAndArgs...)
+}
+
+// NotNilf asserts that the specified object is not nil.
+//
+// a.NotNilf(err, "error message %s", "formatted")
+func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotNilf(a.t, object, msg, args...)
+}
+
+// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
+//
+// a.NotPanics(func(){ RemainCalm() })
+func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotPanics(a.t, f, msgAndArgs...)
+}
+
+// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic.
+//
+// a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted")
+func (a *Assertions) NotPanicsf(f PanicTestFunc, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotPanicsf(a.t, f, msg, args...)
+}
+
+// NotRegexp asserts that a specified regexp does not match a string.
+//
+// a.NotRegexp(regexp.MustCompile("starts"), "it's starting")
+// a.NotRegexp("^start", "it's not starting")
+func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotRegexp(a.t, rx, str, msgAndArgs...)
+}
+
+// NotRegexpf asserts that a specified regexp does not match a string.
+//
+// a.NotRegexpf(regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting")
+// a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted")
+func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotRegexpf(a.t, rx, str, msg, args...)
+}
+
+// NotSubset asserts that the specified list(array, slice...) contains not all
+// elements given in the specified subset(array, slice...).
+//
+// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]")
+func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotSubset(a.t, list, subset, msgAndArgs...)
+}
+
+// NotSubsetf asserts that the specified list(array, slice...) contains not all
+// elements given in the specified subset(array, slice...).
+//
+// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted")
+func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotSubsetf(a.t, list, subset, msg, args...)
+}
+
+// NotZero asserts that i is not the zero value for its type.
+func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotZero(a.t, i, msgAndArgs...)
+}
+
+// NotZerof asserts that i is not the zero value for its type.
+func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotZerof(a.t, i, msg, args...)
+}
+
+// Panics asserts that the code inside the specified PanicTestFunc panics.
+//
+// a.Panics(func(){ GoCrazy() })
+func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Panics(a.t, f, msgAndArgs...)
+}
+
+// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that
+// the recovered panic value equals the expected panic value.
+//
+// a.PanicsWithValue("crazy error", func(){ GoCrazy() })
+func (a *Assertions) PanicsWithValue(expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return PanicsWithValue(a.t, expected, f, msgAndArgs...)
+}
+
+// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that
+// the recovered panic value equals the expected panic value.
+//
+// a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
+func (a *Assertions) PanicsWithValuef(expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return PanicsWithValuef(a.t, expected, f, msg, args...)
+}
+
+// Panicsf asserts that the code inside the specified PanicTestFunc panics.
+//
+// a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted")
+func (a *Assertions) Panicsf(f PanicTestFunc, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Panicsf(a.t, f, msg, args...)
+}
+
+// Regexp asserts that a specified regexp matches a string.
+//
+// a.Regexp(regexp.MustCompile("start"), "it's starting")
+// a.Regexp("start...$", "it's not starting")
+func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Regexp(a.t, rx, str, msgAndArgs...)
+}
+
+// Regexpf asserts that a specified regexp matches a string.
+//
+// a.Regexpf(regexp.MustCompile("start", "error message %s", "formatted"), "it's starting")
+// a.Regexpf("start...$", "it's not starting", "error message %s", "formatted")
+func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Regexpf(a.t, rx, str, msg, args...)
+}
+
+// Subset asserts that the specified list(array, slice...) contains all
+// elements given in the specified subset(array, slice...).
+//
+// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]")
+func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Subset(a.t, list, subset, msgAndArgs...)
+}
+
+// Subsetf asserts that the specified list(array, slice...) contains all
+// elements given in the specified subset(array, slice...).
+//
+// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted")
+func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Subsetf(a.t, list, subset, msg, args...)
+}
+
+// True asserts that the specified value is true.
+//
+// a.True(myBool)
+func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return True(a.t, value, msgAndArgs...)
+}
+
+// Truef asserts that the specified value is true.
+//
+// a.Truef(myBool, "error message %s", "formatted")
+func (a *Assertions) Truef(value bool, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Truef(a.t, value, msg, args...)
+}
+
+// WithinDuration asserts that the two times are within duration delta of each other.
+//
+// a.WithinDuration(time.Now(), time.Now(), 10*time.Second)
+func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return WithinDuration(a.t, expected, actual, delta, msgAndArgs...)
+}
+
+// WithinDurationf asserts that the two times are within duration delta of each other.
+//
+// a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted")
+func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return WithinDurationf(a.t, expected, actual, delta, msg, args...)
+}
+
+// Zero asserts that i is the zero value for its type.
+func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Zero(a.t, i, msgAndArgs...)
+}
+
+// Zerof asserts that i is the zero value for its type.
+func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Zerof(a.t, i, msg, args...)
+}
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl b/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl
new file mode 100644
index 000000000..188bb9e17
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl
@@ -0,0 +1,5 @@
+{{.CommentWithoutT "a"}}
+func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) bool {
+ if h, ok := a.t.(tHelper); ok { h.Helper() }
+ return {{.DocInfo.Name}}(a.t, {{.ForwardedParams}})
+}
diff --git a/vendor/github.com/stretchr/testify/assert/assertions.go b/vendor/github.com/stretchr/testify/assert/assertions.go
new file mode 100644
index 000000000..9bd4a80e4
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/assertions.go
@@ -0,0 +1,1416 @@
+package assert
+
+import (
+ "bufio"
+ "bytes"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "math"
+ "os"
+ "reflect"
+ "regexp"
+ "runtime"
+ "strings"
+ "time"
+ "unicode"
+ "unicode/utf8"
+
+ "github.com/davecgh/go-spew/spew"
+ "github.com/pmezard/go-difflib/difflib"
+)
+
+//go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_format.go.tmpl
+
+// TestingT is an interface wrapper around *testing.T
+type TestingT interface {
+ Errorf(format string, args ...interface{})
+}
+
+// ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful
+// for table driven tests.
+type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{}) bool
+
+// ValueAssertionFunc is a common function prototype when validating a single value. Can be useful
+// for table driven tests.
+type ValueAssertionFunc func(TestingT, interface{}, ...interface{}) bool
+
+// BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful
+// for table driven tests.
+type BoolAssertionFunc func(TestingT, bool, ...interface{}) bool
+
+// ErrorAssertionFunc is a common function prototype when validating an error value. Can be useful
+// for table driven tests.
+type ErrorAssertionFunc func(TestingT, error, ...interface{}) bool
+
+// Comparison a custom function that returns true on success and false on failure
+type Comparison func() (success bool)
+
+/*
+ Helper functions
+*/
+
+// ObjectsAreEqual determines if two objects are considered equal.
+//
+// This function does no assertion of any kind.
+func ObjectsAreEqual(expected, actual interface{}) bool {
+ if expected == nil || actual == nil {
+ return expected == actual
+ }
+
+ exp, ok := expected.([]byte)
+ if !ok {
+ return reflect.DeepEqual(expected, actual)
+ }
+
+ act, ok := actual.([]byte)
+ if !ok {
+ return false
+ }
+ if exp == nil || act == nil {
+ return exp == nil && act == nil
+ }
+ return bytes.Equal(exp, act)
+}
+
+// ObjectsAreEqualValues gets whether two objects are equal, or if their
+// values are equal.
+func ObjectsAreEqualValues(expected, actual interface{}) bool {
+ if ObjectsAreEqual(expected, actual) {
+ return true
+ }
+
+ actualType := reflect.TypeOf(actual)
+ if actualType == nil {
+ return false
+ }
+ expectedValue := reflect.ValueOf(expected)
+ if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) {
+ // Attempt comparison after type conversion
+ return reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual)
+ }
+
+ return false
+}
+
+/* CallerInfo is necessary because the assert functions use the testing object
+internally, causing it to print the file:line of the assert method, rather than where
+the problem actually occurred in calling code.*/
+
+// CallerInfo returns an array of strings containing the file and line number
+// of each stack frame leading from the current test to the assert call that
+// failed.
+func CallerInfo() []string {
+
+ pc := uintptr(0)
+ file := ""
+ line := 0
+ ok := false
+ name := ""
+
+ callers := []string{}
+ for i := 0; ; i++ {
+ pc, file, line, ok = runtime.Caller(i)
+ if !ok {
+ // The breaks below failed to terminate the loop, and we ran off the
+ // end of the call stack.
+ break
+ }
+
+ // This is a huge edge case, but it will panic if this is the case, see #180
+ if file == "" {
+ break
+ }
+
+ f := runtime.FuncForPC(pc)
+ if f == nil {
+ break
+ }
+ name = f.Name()
+
+ // testing.tRunner is the standard library function that calls
+ // tests. Subtests are called directly by tRunner, without going through
+ // the Test/Benchmark/Example function that contains the t.Run calls, so
+ // with subtests we should break when we hit tRunner, without adding it
+ // to the list of callers.
+ if name == "testing.tRunner" {
+ break
+ }
+
+ parts := strings.Split(file, "/")
+ file = parts[len(parts)-1]
+ if len(parts) > 1 {
+ dir := parts[len(parts)-2]
+ if (dir != "assert" && dir != "mock" && dir != "require") || file == "mock_test.go" {
+ callers = append(callers, fmt.Sprintf("%s:%d", file, line))
+ }
+ }
+
+ // Drop the package
+ segments := strings.Split(name, ".")
+ name = segments[len(segments)-1]
+ if isTest(name, "Test") ||
+ isTest(name, "Benchmark") ||
+ isTest(name, "Example") {
+ break
+ }
+ }
+
+ return callers
+}
+
+// Stolen from the `go test` tool.
+// isTest tells whether name looks like a test (or benchmark, according to prefix).
+// It is a Test (say) if there is a character after Test that is not a lower-case letter.
+// We don't want TesticularCancer.
+func isTest(name, prefix string) bool {
+ if !strings.HasPrefix(name, prefix) {
+ return false
+ }
+ if len(name) == len(prefix) { // "Test" is ok
+ return true
+ }
+ rune, _ := utf8.DecodeRuneInString(name[len(prefix):])
+ return !unicode.IsLower(rune)
+}
+
+func messageFromMsgAndArgs(msgAndArgs ...interface{}) string {
+ if len(msgAndArgs) == 0 || msgAndArgs == nil {
+ return ""
+ }
+ if len(msgAndArgs) == 1 {
+ msg := msgAndArgs[0]
+ if msgAsStr, ok := msg.(string); ok {
+ return msgAsStr
+ }
+ return fmt.Sprintf("%+v", msg)
+ }
+ if len(msgAndArgs) > 1 {
+ return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...)
+ }
+ return ""
+}
+
+// Aligns the provided message so that all lines after the first line start at the same location as the first line.
+// Assumes that the first line starts at the correct location (after carriage return, tab, label, spacer and tab).
+// The longestLabelLen parameter specifies the length of the longest label in the output (required becaues this is the
+// basis on which the alignment occurs).
+func indentMessageLines(message string, longestLabelLen int) string {
+ outBuf := new(bytes.Buffer)
+
+ for i, scanner := 0, bufio.NewScanner(strings.NewReader(message)); scanner.Scan(); i++ {
+ // no need to align first line because it starts at the correct location (after the label)
+ if i != 0 {
+ // append alignLen+1 spaces to align with "{{longestLabel}}:" before adding tab
+ outBuf.WriteString("\n\t" + strings.Repeat(" ", longestLabelLen+1) + "\t")
+ }
+ outBuf.WriteString(scanner.Text())
+ }
+
+ return outBuf.String()
+}
+
+type failNower interface {
+ FailNow()
+}
+
+// FailNow fails test
+func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ Fail(t, failureMessage, msgAndArgs...)
+
+ // We cannot extend TestingT with FailNow() and
+ // maintain backwards compatibility, so we fallback
+ // to panicking when FailNow is not available in
+ // TestingT.
+ // See issue #263
+
+ if t, ok := t.(failNower); ok {
+ t.FailNow()
+ } else {
+ panic("test failed and t is missing `FailNow()`")
+ }
+ return false
+}
+
+// Fail reports a failure through
+func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ content := []labeledContent{
+ {"Error Trace", strings.Join(CallerInfo(), "\n\t\t\t")},
+ {"Error", failureMessage},
+ }
+
+ // Add test name if the Go version supports it
+ if n, ok := t.(interface {
+ Name() string
+ }); ok {
+ content = append(content, labeledContent{"Test", n.Name()})
+ }
+
+ message := messageFromMsgAndArgs(msgAndArgs...)
+ if len(message) > 0 {
+ content = append(content, labeledContent{"Messages", message})
+ }
+
+ t.Errorf("\n%s", ""+labeledOutput(content...))
+
+ return false
+}
+
+type labeledContent struct {
+ label string
+ content string
+}
+
+// labeledOutput returns a string consisting of the provided labeledContent. Each labeled output is appended in the following manner:
+//
+// \t{{label}}:{{align_spaces}}\t{{content}}\n
+//
+// The initial carriage return is required to undo/erase any padding added by testing.T.Errorf. The "\t{{label}}:" is for the label.
+// If a label is shorter than the longest label provided, padding spaces are added to make all the labels match in length. Once this
+// alignment is achieved, "\t{{content}}\n" is added for the output.
+//
+// If the content of the labeledOutput contains line breaks, the subsequent lines are aligned so that they start at the same location as the first line.
+func labeledOutput(content ...labeledContent) string {
+ longestLabel := 0
+ for _, v := range content {
+ if len(v.label) > longestLabel {
+ longestLabel = len(v.label)
+ }
+ }
+ var output string
+ for _, v := range content {
+ output += "\t" + v.label + ":" + strings.Repeat(" ", longestLabel-len(v.label)) + "\t" + indentMessageLines(v.content, longestLabel) + "\n"
+ }
+ return output
+}
+
+// Implements asserts that an object is implemented by the specified interface.
+//
+// assert.Implements(t, (*MyInterface)(nil), new(MyObject))
+func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ interfaceType := reflect.TypeOf(interfaceObject).Elem()
+
+ if object == nil {
+ return Fail(t, fmt.Sprintf("Cannot check if nil implements %v", interfaceType), msgAndArgs...)
+ }
+ if !reflect.TypeOf(object).Implements(interfaceType) {
+ return Fail(t, fmt.Sprintf("%T must implement %v", object, interfaceType), msgAndArgs...)
+ }
+
+ return true
+}
+
+// IsType asserts that the specified objects are of the same type.
+func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) {
+ return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...)
+ }
+
+ return true
+}
+
+// Equal asserts that two objects are equal.
+//
+// assert.Equal(t, 123, 123)
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses). Function equality
+// cannot be determined and will always fail.
+func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if err := validateEqualArgs(expected, actual); err != nil {
+ return Fail(t, fmt.Sprintf("Invalid operation: %#v == %#v (%s)",
+ expected, actual, err), msgAndArgs...)
+ }
+
+ if !ObjectsAreEqual(expected, actual) {
+ diff := diff(expected, actual)
+ expected, actual = formatUnequalValues(expected, actual)
+ return Fail(t, fmt.Sprintf("Not equal: \n"+
+ "expected: %s\n"+
+ "actual : %s%s", expected, actual, diff), msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// formatUnequalValues takes two values of arbitrary types and returns string
+// representations appropriate to be presented to the user.
+//
+// If the values are not of like type, the returned strings will be prefixed
+// with the type name, and the value will be enclosed in parenthesis similar
+// to a type conversion in the Go grammar.
+func formatUnequalValues(expected, actual interface{}) (e string, a string) {
+ if reflect.TypeOf(expected) != reflect.TypeOf(actual) {
+ return fmt.Sprintf("%T(%#v)", expected, expected),
+ fmt.Sprintf("%T(%#v)", actual, actual)
+ }
+
+ return fmt.Sprintf("%#v", expected),
+ fmt.Sprintf("%#v", actual)
+}
+
+// EqualValues asserts that two objects are equal or convertable to the same types
+// and equal.
+//
+// assert.EqualValues(t, uint32(123), int32(123))
+func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ if !ObjectsAreEqualValues(expected, actual) {
+ diff := diff(expected, actual)
+ expected, actual = formatUnequalValues(expected, actual)
+ return Fail(t, fmt.Sprintf("Not equal: \n"+
+ "expected: %s\n"+
+ "actual : %s%s", expected, actual, diff), msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// Exactly asserts that two objects are equal in value and type.
+//
+// assert.Exactly(t, int32(123), int64(123))
+func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ aType := reflect.TypeOf(expected)
+ bType := reflect.TypeOf(actual)
+
+ if aType != bType {
+ return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...)
+ }
+
+ return Equal(t, expected, actual, msgAndArgs...)
+
+}
+
+// NotNil asserts that the specified object is not nil.
+//
+// assert.NotNil(t, err)
+func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if !isNil(object) {
+ return true
+ }
+ return Fail(t, "Expected value not to be nil.", msgAndArgs...)
+}
+
+// containsKind checks if a specified kind in the slice of kinds.
+func containsKind(kinds []reflect.Kind, kind reflect.Kind) bool {
+ for i := 0; i < len(kinds); i++ {
+ if kind == kinds[i] {
+ return true
+ }
+ }
+
+ return false
+}
+
+// isNil checks if a specified object is nil or not, without Failing.
+func isNil(object interface{}) bool {
+ if object == nil {
+ return true
+ }
+
+ value := reflect.ValueOf(object)
+ kind := value.Kind()
+ isNilableKind := containsKind(
+ []reflect.Kind{
+ reflect.Chan, reflect.Func,
+ reflect.Interface, reflect.Map,
+ reflect.Ptr, reflect.Slice},
+ kind)
+
+ if isNilableKind && value.IsNil() {
+ return true
+ }
+
+ return false
+}
+
+// Nil asserts that the specified object is nil.
+//
+// assert.Nil(t, err)
+func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if isNil(object) {
+ return true
+ }
+ return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...)
+}
+
+// isEmpty gets whether the specified object is considered empty or not.
+func isEmpty(object interface{}) bool {
+
+ // get nil case out of the way
+ if object == nil {
+ return true
+ }
+
+ objValue := reflect.ValueOf(object)
+
+ switch objValue.Kind() {
+ // collection types are empty when they have no element
+ case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
+ return objValue.Len() == 0
+ // pointers are empty if nil or if the value they point to is empty
+ case reflect.Ptr:
+ if objValue.IsNil() {
+ return true
+ }
+ deref := objValue.Elem().Interface()
+ return isEmpty(deref)
+ // for all other types, compare against the zero value
+ default:
+ zero := reflect.Zero(objValue.Type())
+ return reflect.DeepEqual(object, zero.Interface())
+ }
+}
+
+// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// assert.Empty(t, obj)
+func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ pass := isEmpty(object)
+ if !pass {
+ Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...)
+ }
+
+ return pass
+
+}
+
+// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// if assert.NotEmpty(t, obj) {
+// assert.Equal(t, "two", obj[1])
+// }
+func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ pass := !isEmpty(object)
+ if !pass {
+ Fail(t, fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...)
+ }
+
+ return pass
+
+}
+
+// getLen try to get length of object.
+// return (false, 0) if impossible.
+func getLen(x interface{}) (ok bool, length int) {
+ v := reflect.ValueOf(x)
+ defer func() {
+ if e := recover(); e != nil {
+ ok = false
+ }
+ }()
+ return true, v.Len()
+}
+
+// Len asserts that the specified object has specific length.
+// Len also fails if the object has a type that len() not accept.
+//
+// assert.Len(t, mySlice, 3)
+func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ ok, l := getLen(object)
+ if !ok {
+ return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...)
+ }
+
+ if l != length {
+ return Fail(t, fmt.Sprintf("\"%s\" should have %d item(s), but has %d", object, length, l), msgAndArgs...)
+ }
+ return true
+}
+
+// True asserts that the specified value is true.
+//
+// assert.True(t, myBool)
+func True(t TestingT, value bool, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if h, ok := t.(interface {
+ Helper()
+ }); ok {
+ h.Helper()
+ }
+
+ if value != true {
+ return Fail(t, "Should be true", msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// False asserts that the specified value is false.
+//
+// assert.False(t, myBool)
+func False(t TestingT, value bool, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ if value != false {
+ return Fail(t, "Should be false", msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// NotEqual asserts that the specified values are NOT equal.
+//
+// assert.NotEqual(t, obj1, obj2)
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses).
+func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if err := validateEqualArgs(expected, actual); err != nil {
+ return Fail(t, fmt.Sprintf("Invalid operation: %#v != %#v (%s)",
+ expected, actual, err), msgAndArgs...)
+ }
+
+ if ObjectsAreEqual(expected, actual) {
+ return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// containsElement try loop over the list check if the list includes the element.
+// return (false, false) if impossible.
+// return (true, false) if element was not found.
+// return (true, true) if element was found.
+func includeElement(list interface{}, element interface{}) (ok, found bool) {
+
+ listValue := reflect.ValueOf(list)
+ elementValue := reflect.ValueOf(element)
+ defer func() {
+ if e := recover(); e != nil {
+ ok = false
+ found = false
+ }
+ }()
+
+ if reflect.TypeOf(list).Kind() == reflect.String {
+ return true, strings.Contains(listValue.String(), elementValue.String())
+ }
+
+ if reflect.TypeOf(list).Kind() == reflect.Map {
+ mapKeys := listValue.MapKeys()
+ for i := 0; i < len(mapKeys); i++ {
+ if ObjectsAreEqual(mapKeys[i].Interface(), element) {
+ return true, true
+ }
+ }
+ return true, false
+ }
+
+ for i := 0; i < listValue.Len(); i++ {
+ if ObjectsAreEqual(listValue.Index(i).Interface(), element) {
+ return true, true
+ }
+ }
+ return true, false
+
+}
+
+// Contains asserts that the specified string, list(array, slice...) or map contains the
+// specified substring or element.
+//
+// assert.Contains(t, "Hello World", "World")
+// assert.Contains(t, ["Hello", "World"], "World")
+// assert.Contains(t, {"Hello": "World"}, "Hello")
+func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ ok, found := includeElement(s, contains)
+ if !ok {
+ return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...)
+ }
+ if !found {
+ return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", s, contains), msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the
+// specified substring or element.
+//
+// assert.NotContains(t, "Hello World", "Earth")
+// assert.NotContains(t, ["Hello", "World"], "Earth")
+// assert.NotContains(t, {"Hello": "World"}, "Earth")
+func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ ok, found := includeElement(s, contains)
+ if !ok {
+ return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...)
+ }
+ if found {
+ return Fail(t, fmt.Sprintf("\"%s\" should not contain \"%s\"", s, contains), msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// Subset asserts that the specified list(array, slice...) contains all
+// elements given in the specified subset(array, slice...).
+//
+// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]")
+func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if subset == nil {
+ return true // we consider nil to be equal to the nil set
+ }
+
+ subsetValue := reflect.ValueOf(subset)
+ defer func() {
+ if e := recover(); e != nil {
+ ok = false
+ }
+ }()
+
+ listKind := reflect.TypeOf(list).Kind()
+ subsetKind := reflect.TypeOf(subset).Kind()
+
+ if listKind != reflect.Array && listKind != reflect.Slice {
+ return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...)
+ }
+
+ if subsetKind != reflect.Array && subsetKind != reflect.Slice {
+ return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...)
+ }
+
+ for i := 0; i < subsetValue.Len(); i++ {
+ element := subsetValue.Index(i).Interface()
+ ok, found := includeElement(list, element)
+ if !ok {
+ return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...)
+ }
+ if !found {
+ return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", list, element), msgAndArgs...)
+ }
+ }
+
+ return true
+}
+
+// NotSubset asserts that the specified list(array, slice...) contains not all
+// elements given in the specified subset(array, slice...).
+//
+// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]")
+func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if subset == nil {
+ return Fail(t, fmt.Sprintf("nil is the empty set which is a subset of every set"), msgAndArgs...)
+ }
+
+ subsetValue := reflect.ValueOf(subset)
+ defer func() {
+ if e := recover(); e != nil {
+ ok = false
+ }
+ }()
+
+ listKind := reflect.TypeOf(list).Kind()
+ subsetKind := reflect.TypeOf(subset).Kind()
+
+ if listKind != reflect.Array && listKind != reflect.Slice {
+ return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...)
+ }
+
+ if subsetKind != reflect.Array && subsetKind != reflect.Slice {
+ return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...)
+ }
+
+ for i := 0; i < subsetValue.Len(); i++ {
+ element := subsetValue.Index(i).Interface()
+ ok, found := includeElement(list, element)
+ if !ok {
+ return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...)
+ }
+ if !found {
+ return true
+ }
+ }
+
+ return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...)
+}
+
+// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified
+// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
+// the number of appearances of each of them in both lists should match.
+//
+// assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2])
+func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface{}) (ok bool) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if isEmpty(listA) && isEmpty(listB) {
+ return true
+ }
+
+ aKind := reflect.TypeOf(listA).Kind()
+ bKind := reflect.TypeOf(listB).Kind()
+
+ if aKind != reflect.Array && aKind != reflect.Slice {
+ return Fail(t, fmt.Sprintf("%q has an unsupported type %s", listA, aKind), msgAndArgs...)
+ }
+
+ if bKind != reflect.Array && bKind != reflect.Slice {
+ return Fail(t, fmt.Sprintf("%q has an unsupported type %s", listB, bKind), msgAndArgs...)
+ }
+
+ aValue := reflect.ValueOf(listA)
+ bValue := reflect.ValueOf(listB)
+
+ aLen := aValue.Len()
+ bLen := bValue.Len()
+
+ if aLen != bLen {
+ return Fail(t, fmt.Sprintf("lengths don't match: %d != %d", aLen, bLen), msgAndArgs...)
+ }
+
+ // Mark indexes in bValue that we already used
+ visited := make([]bool, bLen)
+ for i := 0; i < aLen; i++ {
+ element := aValue.Index(i).Interface()
+ found := false
+ for j := 0; j < bLen; j++ {
+ if visited[j] {
+ continue
+ }
+ if ObjectsAreEqual(bValue.Index(j).Interface(), element) {
+ visited[j] = true
+ found = true
+ break
+ }
+ }
+ if !found {
+ return Fail(t, fmt.Sprintf("element %s appears more times in %s than in %s", element, aValue, bValue), msgAndArgs...)
+ }
+ }
+
+ return true
+}
+
+// Condition uses a Comparison to assert a complex condition.
+func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ result := comp()
+ if !result {
+ Fail(t, "Condition failed!", msgAndArgs...)
+ }
+ return result
+}
+
+// PanicTestFunc defines a func that should be passed to the assert.Panics and assert.NotPanics
+// methods, and represents a simple func that takes no arguments, and returns nothing.
+type PanicTestFunc func()
+
+// didPanic returns true if the function passed to it panics. Otherwise, it returns false.
+func didPanic(f PanicTestFunc) (bool, interface{}) {
+
+ didPanic := false
+ var message interface{}
+ func() {
+
+ defer func() {
+ if message = recover(); message != nil {
+ didPanic = true
+ }
+ }()
+
+ // call the target function
+ f()
+
+ }()
+
+ return didPanic, message
+
+}
+
+// Panics asserts that the code inside the specified PanicTestFunc panics.
+//
+// assert.Panics(t, func(){ GoCrazy() })
+func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ if funcDidPanic, panicValue := didPanic(f); !funcDidPanic {
+ return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...)
+ }
+
+ return true
+}
+
+// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that
+// the recovered panic value equals the expected panic value.
+//
+// assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() })
+func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ funcDidPanic, panicValue := didPanic(f)
+ if !funcDidPanic {
+ return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...)
+ }
+ if panicValue != expected {
+ return Fail(t, fmt.Sprintf("func %#v should panic with value:\t%#v\n\tPanic value:\t%#v", f, expected, panicValue), msgAndArgs...)
+ }
+
+ return true
+}
+
+// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
+//
+// assert.NotPanics(t, func(){ RemainCalm() })
+func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ if funcDidPanic, panicValue := didPanic(f); funcDidPanic {
+ return Fail(t, fmt.Sprintf("func %#v should not panic\n\tPanic value:\t%v", f, panicValue), msgAndArgs...)
+ }
+
+ return true
+}
+
+// WithinDuration asserts that the two times are within duration delta of each other.
+//
+// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second)
+func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ dt := expected.Sub(actual)
+ if dt < -delta || dt > delta {
+ return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...)
+ }
+
+ return true
+}
+
+func toFloat(x interface{}) (float64, bool) {
+ var xf float64
+ xok := true
+
+ switch xn := x.(type) {
+ case uint8:
+ xf = float64(xn)
+ case uint16:
+ xf = float64(xn)
+ case uint32:
+ xf = float64(xn)
+ case uint64:
+ xf = float64(xn)
+ case int:
+ xf = float64(xn)
+ case int8:
+ xf = float64(xn)
+ case int16:
+ xf = float64(xn)
+ case int32:
+ xf = float64(xn)
+ case int64:
+ xf = float64(xn)
+ case float32:
+ xf = float64(xn)
+ case float64:
+ xf = float64(xn)
+ case time.Duration:
+ xf = float64(xn)
+ default:
+ xok = false
+ }
+
+ return xf, xok
+}
+
+// InDelta asserts that the two numerals are within delta of each other.
+//
+// assert.InDelta(t, math.Pi, (22 / 7.0), 0.01)
+func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ af, aok := toFloat(expected)
+ bf, bok := toFloat(actual)
+
+ if !aok || !bok {
+ return Fail(t, fmt.Sprintf("Parameters must be numerical"), msgAndArgs...)
+ }
+
+ if math.IsNaN(af) {
+ return Fail(t, fmt.Sprintf("Expected must not be NaN"), msgAndArgs...)
+ }
+
+ if math.IsNaN(bf) {
+ return Fail(t, fmt.Sprintf("Expected %v with delta %v, but was NaN", expected, delta), msgAndArgs...)
+ }
+
+ dt := af - bf
+ if dt < -delta || dt > delta {
+ return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...)
+ }
+
+ return true
+}
+
+// InDeltaSlice is the same as InDelta, except it compares two slices.
+func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if expected == nil || actual == nil ||
+ reflect.TypeOf(actual).Kind() != reflect.Slice ||
+ reflect.TypeOf(expected).Kind() != reflect.Slice {
+ return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...)
+ }
+
+ actualSlice := reflect.ValueOf(actual)
+ expectedSlice := reflect.ValueOf(expected)
+
+ for i := 0; i < actualSlice.Len(); i++ {
+ result := InDelta(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta, msgAndArgs...)
+ if !result {
+ return result
+ }
+ }
+
+ return true
+}
+
+// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
+func InDeltaMapValues(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if expected == nil || actual == nil ||
+ reflect.TypeOf(actual).Kind() != reflect.Map ||
+ reflect.TypeOf(expected).Kind() != reflect.Map {
+ return Fail(t, "Arguments must be maps", msgAndArgs...)
+ }
+
+ expectedMap := reflect.ValueOf(expected)
+ actualMap := reflect.ValueOf(actual)
+
+ if expectedMap.Len() != actualMap.Len() {
+ return Fail(t, "Arguments must have the same number of keys", msgAndArgs...)
+ }
+
+ for _, k := range expectedMap.MapKeys() {
+ ev := expectedMap.MapIndex(k)
+ av := actualMap.MapIndex(k)
+
+ if !ev.IsValid() {
+ return Fail(t, fmt.Sprintf("missing key %q in expected map", k), msgAndArgs...)
+ }
+
+ if !av.IsValid() {
+ return Fail(t, fmt.Sprintf("missing key %q in actual map", k), msgAndArgs...)
+ }
+
+ if !InDelta(
+ t,
+ ev.Interface(),
+ av.Interface(),
+ delta,
+ msgAndArgs...,
+ ) {
+ return false
+ }
+ }
+
+ return true
+}
+
+func calcRelativeError(expected, actual interface{}) (float64, error) {
+ af, aok := toFloat(expected)
+ if !aok {
+ return 0, fmt.Errorf("expected value %q cannot be converted to float", expected)
+ }
+ if af == 0 {
+ return 0, fmt.Errorf("expected value must have a value other than zero to calculate the relative error")
+ }
+ bf, bok := toFloat(actual)
+ if !bok {
+ return 0, fmt.Errorf("actual value %q cannot be converted to float", actual)
+ }
+
+ return math.Abs(af-bf) / math.Abs(af), nil
+}
+
+// InEpsilon asserts that expected and actual have a relative error less than epsilon
+func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ actualEpsilon, err := calcRelativeError(expected, actual)
+ if err != nil {
+ return Fail(t, err.Error(), msgAndArgs...)
+ }
+ if actualEpsilon > epsilon {
+ return Fail(t, fmt.Sprintf("Relative error is too high: %#v (expected)\n"+
+ " < %#v (actual)", epsilon, actualEpsilon), msgAndArgs...)
+ }
+
+ return true
+}
+
+// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices.
+func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if expected == nil || actual == nil ||
+ reflect.TypeOf(actual).Kind() != reflect.Slice ||
+ reflect.TypeOf(expected).Kind() != reflect.Slice {
+ return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...)
+ }
+
+ actualSlice := reflect.ValueOf(actual)
+ expectedSlice := reflect.ValueOf(expected)
+
+ for i := 0; i < actualSlice.Len(); i++ {
+ result := InEpsilon(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), epsilon)
+ if !result {
+ return result
+ }
+ }
+
+ return true
+}
+
+/*
+ Errors
+*/
+
+// NoError asserts that a function returned no error (i.e. `nil`).
+//
+// actualObj, err := SomeFunction()
+// if assert.NoError(t, err) {
+// assert.Equal(t, expectedObj, actualObj)
+// }
+func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if err != nil {
+ return Fail(t, fmt.Sprintf("Received unexpected error:\n%+v", err), msgAndArgs...)
+ }
+
+ return true
+}
+
+// Error asserts that a function returned an error (i.e. not `nil`).
+//
+// actualObj, err := SomeFunction()
+// if assert.Error(t, err) {
+// assert.Equal(t, expectedError, err)
+// }
+func Error(t TestingT, err error, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ if err == nil {
+ return Fail(t, "An error is expected but got nil.", msgAndArgs...)
+ }
+
+ return true
+}
+
+// EqualError asserts that a function returned an error (i.e. not `nil`)
+// and that it is equal to the provided error.
+//
+// actualObj, err := SomeFunction()
+// assert.EqualError(t, err, expectedErrorString)
+func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if !Error(t, theError, msgAndArgs...) {
+ return false
+ }
+ expected := errString
+ actual := theError.Error()
+ // don't need to use deep equals here, we know they are both strings
+ if expected != actual {
+ return Fail(t, fmt.Sprintf("Error message not equal:\n"+
+ "expected: %q\n"+
+ "actual : %q", expected, actual), msgAndArgs...)
+ }
+ return true
+}
+
+// matchRegexp return true if a specified regexp matches a string.
+func matchRegexp(rx interface{}, str interface{}) bool {
+
+ var r *regexp.Regexp
+ if rr, ok := rx.(*regexp.Regexp); ok {
+ r = rr
+ } else {
+ r = regexp.MustCompile(fmt.Sprint(rx))
+ }
+
+ return (r.FindStringIndex(fmt.Sprint(str)) != nil)
+
+}
+
+// Regexp asserts that a specified regexp matches a string.
+//
+// assert.Regexp(t, regexp.MustCompile("start"), "it's starting")
+// assert.Regexp(t, "start...$", "it's not starting")
+func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ match := matchRegexp(rx, str)
+
+ if !match {
+ Fail(t, fmt.Sprintf("Expect \"%v\" to match \"%v\"", str, rx), msgAndArgs...)
+ }
+
+ return match
+}
+
+// NotRegexp asserts that a specified regexp does not match a string.
+//
+// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting")
+// assert.NotRegexp(t, "^start", "it's not starting")
+func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ match := matchRegexp(rx, str)
+
+ if match {
+ Fail(t, fmt.Sprintf("Expect \"%v\" to NOT match \"%v\"", str, rx), msgAndArgs...)
+ }
+
+ return !match
+
+}
+
+// Zero asserts that i is the zero value for its type.
+func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if i != nil && !reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) {
+ return Fail(t, fmt.Sprintf("Should be zero, but was %v", i), msgAndArgs...)
+ }
+ return true
+}
+
+// NotZero asserts that i is not the zero value for its type.
+func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if i == nil || reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) {
+ return Fail(t, fmt.Sprintf("Should not be zero, but was %v", i), msgAndArgs...)
+ }
+ return true
+}
+
+// FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file.
+func FileExists(t TestingT, path string, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ info, err := os.Lstat(path)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return Fail(t, fmt.Sprintf("unable to find file %q", path), msgAndArgs...)
+ }
+ return Fail(t, fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...)
+ }
+ if info.IsDir() {
+ return Fail(t, fmt.Sprintf("%q is a directory", path), msgAndArgs...)
+ }
+ return true
+}
+
+// DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists.
+func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ info, err := os.Lstat(path)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return Fail(t, fmt.Sprintf("unable to find file %q", path), msgAndArgs...)
+ }
+ return Fail(t, fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...)
+ }
+ if !info.IsDir() {
+ return Fail(t, fmt.Sprintf("%q is a file", path), msgAndArgs...)
+ }
+ return true
+}
+
+// JSONEq asserts that two JSON strings are equivalent.
+//
+// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
+func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ var expectedJSONAsInterface, actualJSONAsInterface interface{}
+
+ if err := json.Unmarshal([]byte(expected), &expectedJSONAsInterface); err != nil {
+ return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid json.\nJSON parsing error: '%s'", expected, err.Error()), msgAndArgs...)
+ }
+
+ if err := json.Unmarshal([]byte(actual), &actualJSONAsInterface); err != nil {
+ return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid json.\nJSON parsing error: '%s'", actual, err.Error()), msgAndArgs...)
+ }
+
+ return Equal(t, expectedJSONAsInterface, actualJSONAsInterface, msgAndArgs...)
+}
+
+func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) {
+ t := reflect.TypeOf(v)
+ k := t.Kind()
+
+ if k == reflect.Ptr {
+ t = t.Elem()
+ k = t.Kind()
+ }
+ return t, k
+}
+
+// diff returns a diff of both values as long as both are of the same type and
+// are a struct, map, slice, array or string. Otherwise it returns an empty string.
+func diff(expected interface{}, actual interface{}) string {
+ if expected == nil || actual == nil {
+ return ""
+ }
+
+ et, ek := typeAndKind(expected)
+ at, _ := typeAndKind(actual)
+
+ if et != at {
+ return ""
+ }
+
+ if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array && ek != reflect.String {
+ return ""
+ }
+
+ var e, a string
+ if et != reflect.TypeOf("") {
+ e = spewConfig.Sdump(expected)
+ a = spewConfig.Sdump(actual)
+ } else {
+ e = expected.(string)
+ a = actual.(string)
+ }
+
+ diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{
+ A: difflib.SplitLines(e),
+ B: difflib.SplitLines(a),
+ FromFile: "Expected",
+ FromDate: "",
+ ToFile: "Actual",
+ ToDate: "",
+ Context: 1,
+ })
+
+ return "\n\nDiff:\n" + diff
+}
+
+// validateEqualArgs checks whether provided arguments can be safely used in the
+// Equal/NotEqual functions.
+func validateEqualArgs(expected, actual interface{}) error {
+ if isFunction(expected) || isFunction(actual) {
+ return errors.New("cannot take func type as argument")
+ }
+ return nil
+}
+
+func isFunction(arg interface{}) bool {
+ if arg == nil {
+ return false
+ }
+ return reflect.TypeOf(arg).Kind() == reflect.Func
+}
+
+var spewConfig = spew.ConfigState{
+ Indent: " ",
+ DisablePointerAddresses: true,
+ DisableCapacities: true,
+ SortKeys: true,
+}
+
+type tHelper interface {
+ Helper()
+}
diff --git a/vendor/github.com/stretchr/testify/assert/doc.go b/vendor/github.com/stretchr/testify/assert/doc.go
new file mode 100644
index 000000000..c9dccc4d6
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/doc.go
@@ -0,0 +1,45 @@
+// Package assert provides a set of comprehensive testing tools for use with the normal Go testing system.
+//
+// Example Usage
+//
+// The following is a complete example using assert in a standard test function:
+// import (
+// "testing"
+// "github.com/stretchr/testify/assert"
+// )
+//
+// func TestSomething(t *testing.T) {
+//
+// var a string = "Hello"
+// var b string = "Hello"
+//
+// assert.Equal(t, a, b, "The two words should be the same.")
+//
+// }
+//
+// if you assert many times, use the format below:
+//
+// import (
+// "testing"
+// "github.com/stretchr/testify/assert"
+// )
+//
+// func TestSomething(t *testing.T) {
+// assert := assert.New(t)
+//
+// var a string = "Hello"
+// var b string = "Hello"
+//
+// assert.Equal(a, b, "The two words should be the same.")
+// }
+//
+// Assertions
+//
+// Assertions allow you to easily write test code, and are global funcs in the `assert` package.
+// All assertion functions take, as the first argument, the `*testing.T` object provided by the
+// testing framework. This allows the assertion funcs to write the failings and other details to
+// the correct place.
+//
+// Every assertion function also takes an optional string message as the final argument,
+// allowing custom error messages to be appended to the message the assertion method outputs.
+package assert
diff --git a/vendor/github.com/stretchr/testify/assert/errors.go b/vendor/github.com/stretchr/testify/assert/errors.go
new file mode 100644
index 000000000..ac9dc9d1d
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/errors.go
@@ -0,0 +1,10 @@
+package assert
+
+import (
+ "errors"
+)
+
+// AnError is an error instance useful for testing. If the code does not care
+// about error specifics, and only needs to return the error for example, this
+// error should be used to make the test code more readable.
+var AnError = errors.New("assert.AnError general error for testing")
diff --git a/vendor/github.com/stretchr/testify/assert/forward_assertions.go b/vendor/github.com/stretchr/testify/assert/forward_assertions.go
new file mode 100644
index 000000000..9ad56851d
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/forward_assertions.go
@@ -0,0 +1,16 @@
+package assert
+
+// Assertions provides assertion methods around the
+// TestingT interface.
+type Assertions struct {
+ t TestingT
+}
+
+// New makes a new Assertions object for the specified TestingT.
+func New(t TestingT) *Assertions {
+ return &Assertions{
+ t: t,
+ }
+}
+
+//go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_forward.go.tmpl -include-format-funcs
diff --git a/vendor/github.com/stretchr/testify/assert/http_assertions.go b/vendor/github.com/stretchr/testify/assert/http_assertions.go
new file mode 100644
index 000000000..df46fa777
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/http_assertions.go
@@ -0,0 +1,143 @@
+package assert
+
+import (
+ "fmt"
+ "net/http"
+ "net/http/httptest"
+ "net/url"
+ "strings"
+)
+
+// httpCode is a helper that returns HTTP code of the response. It returns -1 and
+// an error if building a new request fails.
+func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) {
+ w := httptest.NewRecorder()
+ req, err := http.NewRequest(method, url, nil)
+ if err != nil {
+ return -1, err
+ }
+ req.URL.RawQuery = values.Encode()
+ handler(w, req)
+ return w.Code, nil
+}
+
+// HTTPSuccess asserts that a specified handler returns a success status code.
+//
+// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ code, err := httpCode(handler, method, url, values)
+ if err != nil {
+ Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
+ return false
+ }
+
+ isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent
+ if !isSuccessCode {
+ Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code))
+ }
+
+ return isSuccessCode
+}
+
+// HTTPRedirect asserts that a specified handler returns a redirect status code.
+//
+// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ code, err := httpCode(handler, method, url, values)
+ if err != nil {
+ Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
+ return false
+ }
+
+ isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect
+ if !isRedirectCode {
+ Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code))
+ }
+
+ return isRedirectCode
+}
+
+// HTTPError asserts that a specified handler returns an error status code.
+//
+// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ code, err := httpCode(handler, method, url, values)
+ if err != nil {
+ Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
+ return false
+ }
+
+ isErrorCode := code >= http.StatusBadRequest
+ if !isErrorCode {
+ Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code))
+ }
+
+ return isErrorCode
+}
+
+// HTTPBody is a helper that returns HTTP body of the response. It returns
+// empty string if building a new request fails.
+func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string {
+ w := httptest.NewRecorder()
+ req, err := http.NewRequest(method, url+"?"+values.Encode(), nil)
+ if err != nil {
+ return ""
+ }
+ handler(w, req)
+ return w.Body.String()
+}
+
+// HTTPBodyContains asserts that a specified handler returns a
+// body that contains a string.
+//
+// assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ body := HTTPBody(handler, method, url, values)
+
+ contains := strings.Contains(body, fmt.Sprint(str))
+ if !contains {
+ Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body))
+ }
+
+ return contains
+}
+
+// HTTPBodyNotContains asserts that a specified handler returns a
+// body that does not contain a string.
+//
+// assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ body := HTTPBody(handler, method, url, values)
+
+ contains := strings.Contains(body, fmt.Sprint(str))
+ if contains {
+ Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body))
+ }
+
+ return !contains
+}
diff --git a/vendor/k8s.io/apimachinery/pkg/util/mergepatch/OWNERS b/vendor/k8s.io/apimachinery/pkg/util/mergepatch/OWNERS
new file mode 100644
index 000000000..3f72c69ba
--- /dev/null
+++ b/vendor/k8s.io/apimachinery/pkg/util/mergepatch/OWNERS
@@ -0,0 +1,7 @@
+# See the OWNERS docs at https://go.k8s.io/owners
+
+approvers:
+- pwittrock
+reviewers:
+- mengqiy
+- apelisse
diff --git a/vendor/k8s.io/apimachinery/pkg/util/mergepatch/errors.go b/vendor/k8s.io/apimachinery/pkg/util/mergepatch/errors.go
new file mode 100644
index 000000000..16501d5af
--- /dev/null
+++ b/vendor/k8s.io/apimachinery/pkg/util/mergepatch/errors.go
@@ -0,0 +1,102 @@
+/*
+Copyright 2017 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 mergepatch
+
+import (
+ "errors"
+ "fmt"
+ "reflect"
+)
+
+var (
+ ErrBadJSONDoc = errors.New("invalid JSON document")
+ ErrNoListOfLists = errors.New("lists of lists are not supported")
+ ErrBadPatchFormatForPrimitiveList = errors.New("invalid patch format of primitive list")
+ ErrBadPatchFormatForRetainKeys = errors.New("invalid patch format of retainKeys")
+ ErrBadPatchFormatForSetElementOrderList = errors.New("invalid patch format of setElementOrder list")
+ ErrPatchContentNotMatchRetainKeys = errors.New("patch content doesn't match retainKeys list")
+ ErrUnsupportedStrategicMergePatchFormat = errors.New("strategic merge patch format is not supported")
+)
+
+func ErrNoMergeKey(m map[string]interface{}, k string) error {
+ return fmt.Errorf("map: %v does not contain declared merge key: %s", m, k)
+}
+
+func ErrBadArgType(expected, actual interface{}) error {
+ return fmt.Errorf("expected a %s, but received a %s",
+ reflect.TypeOf(expected),
+ reflect.TypeOf(actual))
+}
+
+func ErrBadArgKind(expected, actual interface{}) error {
+ var expectedKindString, actualKindString string
+ if expected == nil {
+ expectedKindString = "nil"
+ } else {
+ expectedKindString = reflect.TypeOf(expected).Kind().String()
+ }
+ if actual == nil {
+ actualKindString = "nil"
+ } else {
+ actualKindString = reflect.TypeOf(actual).Kind().String()
+ }
+ return fmt.Errorf("expected a %s, but received a %s", expectedKindString, actualKindString)
+}
+
+func ErrBadPatchType(t interface{}, m map[string]interface{}) error {
+ return fmt.Errorf("unknown patch type: %s in map: %v", t, m)
+}
+
+// IsPreconditionFailed returns true if the provided error indicates
+// a precondition failed.
+func IsPreconditionFailed(err error) bool {
+ _, ok := err.(ErrPreconditionFailed)
+ return ok
+}
+
+type ErrPreconditionFailed struct {
+ message string
+}
+
+func NewErrPreconditionFailed(target map[string]interface{}) ErrPreconditionFailed {
+ s := fmt.Sprintf("precondition failed for: %v", target)
+ return ErrPreconditionFailed{s}
+}
+
+func (err ErrPreconditionFailed) Error() string {
+ return err.message
+}
+
+type ErrConflict struct {
+ message string
+}
+
+func NewErrConflict(patch, current string) ErrConflict {
+ s := fmt.Sprintf("patch:\n%s\nconflicts with changes made from original to current:\n%s\n", patch, current)
+ return ErrConflict{s}
+}
+
+func (err ErrConflict) Error() string {
+ return err.message
+}
+
+// IsConflict returns true if the provided error indicates
+// a conflict between the patch and the current configuration.
+func IsConflict(err error) bool {
+ _, ok := err.(ErrConflict)
+ return ok
+}
diff --git a/vendor/k8s.io/apimachinery/pkg/util/mergepatch/util.go b/vendor/k8s.io/apimachinery/pkg/util/mergepatch/util.go
new file mode 100644
index 000000000..990fa0d43
--- /dev/null
+++ b/vendor/k8s.io/apimachinery/pkg/util/mergepatch/util.go
@@ -0,0 +1,133 @@
+/*
+Copyright 2017 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 mergepatch
+
+import (
+ "fmt"
+ "reflect"
+
+ "github.com/davecgh/go-spew/spew"
+ "sigs.k8s.io/yaml"
+)
+
+// PreconditionFunc asserts that an incompatible change is not present within a patch.
+type PreconditionFunc func(interface{}) bool
+
+// RequireKeyUnchanged returns a precondition function that fails if the provided key
+// is present in the patch (indicating that its value has changed).
+func RequireKeyUnchanged(key string) PreconditionFunc {
+ return func(patch interface{}) bool {
+ patchMap, ok := patch.(map[string]interface{})
+ if !ok {
+ return true
+ }
+
+ // The presence of key means that its value has been changed, so the test fails.
+ _, ok = patchMap[key]
+ return !ok
+ }
+}
+
+// RequireMetadataKeyUnchanged creates a precondition function that fails
+// if the metadata.key is present in the patch (indicating its value
+// has changed).
+func RequireMetadataKeyUnchanged(key string) PreconditionFunc {
+ return func(patch interface{}) bool {
+ patchMap, ok := patch.(map[string]interface{})
+ if !ok {
+ return true
+ }
+ patchMap1, ok := patchMap["metadata"]
+ if !ok {
+ return true
+ }
+ patchMap2, ok := patchMap1.(map[string]interface{})
+ if !ok {
+ return true
+ }
+ _, ok = patchMap2[key]
+ return !ok
+ }
+}
+
+func ToYAMLOrError(v interface{}) string {
+ y, err := toYAML(v)
+ if err != nil {
+ return err.Error()
+ }
+
+ return y
+}
+
+func toYAML(v interface{}) (string, error) {
+ y, err := yaml.Marshal(v)
+ if err != nil {
+ return "", fmt.Errorf("yaml marshal failed:%v\n%v\n", err, spew.Sdump(v))
+ }
+
+ return string(y), nil
+}
+
+// HasConflicts returns true if the left and right JSON interface objects overlap with
+// different values in any key. All keys are required to be strings. Since patches of the
+// same Type have congruent keys, this is valid for multiple patch types. This method
+// supports JSON merge patch semantics.
+//
+// NOTE: Numbers with different types (e.g. int(0) vs int64(0)) will be detected as conflicts.
+// Make sure the unmarshaling of left and right are consistent (e.g. use the same library).
+func HasConflicts(left, right interface{}) (bool, error) {
+ switch typedLeft := left.(type) {
+ case map[string]interface{}:
+ switch typedRight := right.(type) {
+ case map[string]interface{}:
+ for key, leftValue := range typedLeft {
+ rightValue, ok := typedRight[key]
+ if !ok {
+ continue
+ }
+ if conflict, err := HasConflicts(leftValue, rightValue); err != nil || conflict {
+ return conflict, err
+ }
+ }
+
+ return false, nil
+ default:
+ return true, nil
+ }
+ case []interface{}:
+ switch typedRight := right.(type) {
+ case []interface{}:
+ if len(typedLeft) != len(typedRight) {
+ return true, nil
+ }
+
+ for i := range typedLeft {
+ if conflict, err := HasConflicts(typedLeft[i], typedRight[i]); err != nil || conflict {
+ return conflict, err
+ }
+ }
+
+ return false, nil
+ default:
+ return true, nil
+ }
+ case string, float64, bool, int64, nil:
+ return !reflect.DeepEqual(left, right), nil
+ default:
+ return true, fmt.Errorf("unknown type: %v", reflect.TypeOf(left))
+ }
+}
diff --git a/vendor/k8s.io/apimachinery/pkg/util/strategicpatch/OWNERS b/vendor/k8s.io/apimachinery/pkg/util/strategicpatch/OWNERS
new file mode 100644
index 000000000..cfee199fa
--- /dev/null
+++ b/vendor/k8s.io/apimachinery/pkg/util/strategicpatch/OWNERS
@@ -0,0 +1,8 @@
+# See the OWNERS docs at https://go.k8s.io/owners
+
+approvers:
+- pwittrock
+- mengqiy
+reviewers:
+- mengqiy
+- apelisse
diff --git a/vendor/k8s.io/apimachinery/pkg/util/strategicpatch/errors.go b/vendor/k8s.io/apimachinery/pkg/util/strategicpatch/errors.go
new file mode 100644
index 000000000..ab66d0452
--- /dev/null
+++ b/vendor/k8s.io/apimachinery/pkg/util/strategicpatch/errors.go
@@ -0,0 +1,49 @@
+/*
+Copyright 2017 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 strategicpatch
+
+import (
+ "fmt"
+)
+
+type LookupPatchMetaError struct {
+ Path string
+ Err error
+}
+
+func (e LookupPatchMetaError) Error() string {
+ return fmt.Sprintf("LookupPatchMetaError(%s): %v", e.Path, e.Err)
+}
+
+type FieldNotFoundError struct {
+ Path string
+ Field string
+}
+
+func (e FieldNotFoundError) Error() string {
+ return fmt.Sprintf("unable to find api field %q in %s", e.Field, e.Path)
+}
+
+type InvalidTypeError struct {
+ Path string
+ Expected string
+ Actual string
+}
+
+func (e InvalidTypeError) Error() string {
+ return fmt.Sprintf("invalid type for %s: got %q, expected %q", e.Path, e.Actual, e.Expected)
+}
diff --git a/vendor/k8s.io/apimachinery/pkg/util/strategicpatch/meta.go b/vendor/k8s.io/apimachinery/pkg/util/strategicpatch/meta.go
new file mode 100644
index 000000000..c31de15e7
--- /dev/null
+++ b/vendor/k8s.io/apimachinery/pkg/util/strategicpatch/meta.go
@@ -0,0 +1,194 @@
+/*
+Copyright 2017 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 strategicpatch
+
+import (
+ "errors"
+ "fmt"
+ "reflect"
+
+ "k8s.io/apimachinery/pkg/util/mergepatch"
+ forkedjson "k8s.io/apimachinery/third_party/forked/golang/json"
+ openapi "k8s.io/kube-openapi/pkg/util/proto"
+)
+
+type PatchMeta struct {
+ patchStrategies []string
+ patchMergeKey string
+}
+
+func (pm PatchMeta) GetPatchStrategies() []string {
+ if pm.patchStrategies == nil {
+ return []string{}
+ }
+ return pm.patchStrategies
+}
+
+func (pm PatchMeta) SetPatchStrategies(ps []string) {
+ pm.patchStrategies = ps
+}
+
+func (pm PatchMeta) GetPatchMergeKey() string {
+ return pm.patchMergeKey
+}
+
+func (pm PatchMeta) SetPatchMergeKey(pmk string) {
+ pm.patchMergeKey = pmk
+}
+
+type LookupPatchMeta interface {
+ // LookupPatchMetadataForStruct gets subschema and the patch metadata (e.g. patch strategy and merge key) for map.
+ LookupPatchMetadataForStruct(key string) (LookupPatchMeta, PatchMeta, error)
+ // LookupPatchMetadataForSlice get subschema and the patch metadata for slice.
+ LookupPatchMetadataForSlice(key string) (LookupPatchMeta, PatchMeta, error)
+ // Get the type name of the field
+ Name() string
+}
+
+type PatchMetaFromStruct struct {
+ T reflect.Type
+}
+
+func NewPatchMetaFromStruct(dataStruct interface{}) (PatchMetaFromStruct, error) {
+ t, err := getTagStructType(dataStruct)
+ return PatchMetaFromStruct{T: t}, err
+}
+
+var _ LookupPatchMeta = PatchMetaFromStruct{}
+
+func (s PatchMetaFromStruct) LookupPatchMetadataForStruct(key string) (LookupPatchMeta, PatchMeta, error) {
+ fieldType, fieldPatchStrategies, fieldPatchMergeKey, err := forkedjson.LookupPatchMetadataForStruct(s.T, key)
+ if err != nil {
+ return nil, PatchMeta{}, err
+ }
+
+ return PatchMetaFromStruct{T: fieldType},
+ PatchMeta{
+ patchStrategies: fieldPatchStrategies,
+ patchMergeKey: fieldPatchMergeKey,
+ }, nil
+}
+
+func (s PatchMetaFromStruct) LookupPatchMetadataForSlice(key string) (LookupPatchMeta, PatchMeta, error) {
+ subschema, patchMeta, err := s.LookupPatchMetadataForStruct(key)
+ if err != nil {
+ return nil, PatchMeta{}, err
+ }
+ elemPatchMetaFromStruct := subschema.(PatchMetaFromStruct)
+ t := elemPatchMetaFromStruct.T
+
+ var elemType reflect.Type
+ switch t.Kind() {
+ // If t is an array or a slice, get the element type.
+ // If element is still an array or a slice, return an error.
+ // Otherwise, return element type.
+ case reflect.Array, reflect.Slice:
+ elemType = t.Elem()
+ if elemType.Kind() == reflect.Array || elemType.Kind() == reflect.Slice {
+ return nil, PatchMeta{}, errors.New("unexpected slice of slice")
+ }
+ // If t is an pointer, get the underlying element.
+ // If the underlying element is neither an array nor a slice, the pointer is pointing to a slice,
+ // e.g. https://github.com/kubernetes/kubernetes/blob/bc22e206c79282487ea0bf5696d5ccec7e839a76/staging/src/k8s.io/apimachinery/pkg/util/strategicpatch/patch_test.go#L2782-L2822
+ // If the underlying element is either an array or a slice, return its element type.
+ case reflect.Ptr:
+ t = t.Elem()
+ if t.Kind() == reflect.Array || t.Kind() == reflect.Slice {
+ t = t.Elem()
+ }
+ elemType = t
+ default:
+ return nil, PatchMeta{}, fmt.Errorf("expected slice or array type, but got: %s", s.T.Kind().String())
+ }
+
+ return PatchMetaFromStruct{T: elemType}, patchMeta, nil
+}
+
+func (s PatchMetaFromStruct) Name() string {
+ return s.T.Kind().String()
+}
+
+func getTagStructType(dataStruct interface{}) (reflect.Type, error) {
+ if dataStruct == nil {
+ return nil, mergepatch.ErrBadArgKind(struct{}{}, nil)
+ }
+
+ t := reflect.TypeOf(dataStruct)
+ // Get the underlying type for pointers
+ if t.Kind() == reflect.Ptr {
+ t = t.Elem()
+ }
+
+ if t.Kind() != reflect.Struct {
+ return nil, mergepatch.ErrBadArgKind(struct{}{}, dataStruct)
+ }
+
+ return t, nil
+}
+
+func GetTagStructTypeOrDie(dataStruct interface{}) reflect.Type {
+ t, err := getTagStructType(dataStruct)
+ if err != nil {
+ panic(err)
+ }
+ return t
+}
+
+type PatchMetaFromOpenAPI struct {
+ Schema openapi.Schema
+}
+
+func NewPatchMetaFromOpenAPI(s openapi.Schema) PatchMetaFromOpenAPI {
+ return PatchMetaFromOpenAPI{Schema: s}
+}
+
+var _ LookupPatchMeta = PatchMetaFromOpenAPI{}
+
+func (s PatchMetaFromOpenAPI) LookupPatchMetadataForStruct(key string) (LookupPatchMeta, PatchMeta, error) {
+ if s.Schema == nil {
+ return nil, PatchMeta{}, nil
+ }
+ kindItem := NewKindItem(key, s.Schema.GetPath())
+ s.Schema.Accept(kindItem)
+
+ err := kindItem.Error()
+ if err != nil {
+ return nil, PatchMeta{}, err
+ }
+ return PatchMetaFromOpenAPI{Schema: kindItem.subschema},
+ kindItem.patchmeta, nil
+}
+
+func (s PatchMetaFromOpenAPI) LookupPatchMetadataForSlice(key string) (LookupPatchMeta, PatchMeta, error) {
+ if s.Schema == nil {
+ return nil, PatchMeta{}, nil
+ }
+ sliceItem := NewSliceItem(key, s.Schema.GetPath())
+ s.Schema.Accept(sliceItem)
+
+ err := sliceItem.Error()
+ if err != nil {
+ return nil, PatchMeta{}, err
+ }
+ return PatchMetaFromOpenAPI{Schema: sliceItem.subschema},
+ sliceItem.patchmeta, nil
+}
+
+func (s PatchMetaFromOpenAPI) Name() string {
+ schema := s.Schema
+ return schema.GetName()
+}
diff --git a/vendor/k8s.io/apimachinery/pkg/util/strategicpatch/patch.go b/vendor/k8s.io/apimachinery/pkg/util/strategicpatch/patch.go
new file mode 100644
index 000000000..ddf998172
--- /dev/null
+++ b/vendor/k8s.io/apimachinery/pkg/util/strategicpatch/patch.go
@@ -0,0 +1,2174 @@
+/*
+Copyright 2014 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 strategicpatch
+
+import (
+ "fmt"
+ "reflect"
+ "sort"
+ "strings"
+
+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+ "k8s.io/apimachinery/pkg/util/json"
+ "k8s.io/apimachinery/pkg/util/mergepatch"
+)
+
+// An alternate implementation of JSON Merge Patch
+// (https://tools.ietf.org/html/rfc7386) which supports the ability to annotate
+// certain fields with metadata that indicates whether the elements of JSON
+// lists should be merged or replaced.
+//
+// For more information, see the PATCH section of docs/devel/api-conventions.md.
+//
+// Some of the content of this package was borrowed with minor adaptations from
+// evanphx/json-patch and openshift/origin.
+
+const (
+ directiveMarker = "$patch"
+ deleteDirective = "delete"
+ replaceDirective = "replace"
+ mergeDirective = "merge"
+
+ retainKeysStrategy = "retainKeys"
+
+ deleteFromPrimitiveListDirectivePrefix = "$deleteFromPrimitiveList"
+ retainKeysDirective = "$" + retainKeysStrategy
+ setElementOrderDirectivePrefix = "$setElementOrder"
+)
+
+// JSONMap is a representations of JSON object encoded as map[string]interface{}
+// where the children can be either map[string]interface{}, []interface{} or
+// primitive type).
+// Operating on JSONMap representation is much faster as it doesn't require any
+// json marshaling and/or unmarshaling operations.
+type JSONMap map[string]interface{}
+
+type DiffOptions struct {
+ // SetElementOrder determines whether we generate the $setElementOrder parallel list.
+ SetElementOrder bool
+ // IgnoreChangesAndAdditions indicates if we keep the changes and additions in the patch.
+ IgnoreChangesAndAdditions bool
+ // IgnoreDeletions indicates if we keep the deletions in the patch.
+ IgnoreDeletions bool
+ // We introduce a new value retainKeys for patchStrategy.
+ // It indicates that all fields needing to be preserved must be
+ // present in the `retainKeys` list.
+ // And the fields that are present will be merged with live object.
+ // All the missing fields will be cleared when patching.
+ BuildRetainKeysDirective bool
+}
+
+type MergeOptions struct {
+ // MergeParallelList indicates if we are merging the parallel list.
+ // We don't merge parallel list when calling mergeMap() in CreateThreeWayMergePatch()
+ // which is called client-side.
+ // We merge parallel list iff when calling mergeMap() in StrategicMergeMapPatch()
+ // which is called server-side
+ MergeParallelList bool
+ // IgnoreUnmatchedNulls indicates if we should process the unmatched nulls.
+ IgnoreUnmatchedNulls bool
+}
+
+// The following code is adapted from github.com/openshift/origin/pkg/util/jsonmerge.
+// Instead of defining a Delta that holds an original, a patch and a set of preconditions,
+// the reconcile method accepts a set of preconditions as an argument.
+
+// CreateTwoWayMergePatch creates a patch that can be passed to StrategicMergePatch from an original
+// document and a modified document, which are passed to the method as json encoded content. It will
+// return a patch that yields the modified document when applied to the original document, or an error
+// if either of the two documents is invalid.
+func CreateTwoWayMergePatch(original, modified []byte, dataStruct interface{}, fns ...mergepatch.PreconditionFunc) ([]byte, error) {
+ schema, err := NewPatchMetaFromStruct(dataStruct)
+ if err != nil {
+ return nil, err
+ }
+
+ return CreateTwoWayMergePatchUsingLookupPatchMeta(original, modified, schema, fns...)
+}
+
+func CreateTwoWayMergePatchUsingLookupPatchMeta(
+ original, modified []byte, schema LookupPatchMeta, fns ...mergepatch.PreconditionFunc) ([]byte, error) {
+ originalMap := map[string]interface{}{}
+ if len(original) > 0 {
+ if err := json.Unmarshal(original, &originalMap); err != nil {
+ return nil, mergepatch.ErrBadJSONDoc
+ }
+ }
+
+ modifiedMap := map[string]interface{}{}
+ if len(modified) > 0 {
+ if err := json.Unmarshal(modified, &modifiedMap); err != nil {
+ return nil, mergepatch.ErrBadJSONDoc
+ }
+ }
+
+ patchMap, err := CreateTwoWayMergeMapPatchUsingLookupPatchMeta(originalMap, modifiedMap, schema, fns...)
+ if err != nil {
+ return nil, err
+ }
+
+ return json.Marshal(patchMap)
+}
+
+// CreateTwoWayMergeMapPatch creates a patch from an original and modified JSON objects,
+// encoded JSONMap.
+// The serialized version of the map can then be passed to StrategicMergeMapPatch.
+func CreateTwoWayMergeMapPatch(original, modified JSONMap, dataStruct interface{}, fns ...mergepatch.PreconditionFunc) (JSONMap, error) {
+ schema, err := NewPatchMetaFromStruct(dataStruct)
+ if err != nil {
+ return nil, err
+ }
+
+ return CreateTwoWayMergeMapPatchUsingLookupPatchMeta(original, modified, schema, fns...)
+}
+
+func CreateTwoWayMergeMapPatchUsingLookupPatchMeta(original, modified JSONMap, schema LookupPatchMeta, fns ...mergepatch.PreconditionFunc) (JSONMap, error) {
+ diffOptions := DiffOptions{
+ SetElementOrder: true,
+ }
+ patchMap, err := diffMaps(original, modified, schema, diffOptions)
+ if err != nil {
+ return nil, err
+ }
+
+ // Apply the preconditions to the patch, and return an error if any of them fail.
+ for _, fn := range fns {
+ if !fn(patchMap) {
+ return nil, mergepatch.NewErrPreconditionFailed(patchMap)
+ }
+ }
+
+ return patchMap, nil
+}
+
+// Returns a (recursive) strategic merge patch that yields modified when applied to original.
+// Including:
+// - Adding fields to the patch present in modified, missing from original
+// - Setting fields to the patch present in modified and original with different values
+// - Delete fields present in original, missing from modified through
+// - IFF map field - set to nil in patch
+// - IFF list of maps && merge strategy - use deleteDirective for the elements
+// - IFF list of primitives && merge strategy - use parallel deletion list
+// - IFF list of maps or primitives with replace strategy (default) - set patch value to the value in modified
+// - Build $retainKeys directive for fields with retainKeys patch strategy
+func diffMaps(original, modified map[string]interface{}, schema LookupPatchMeta, diffOptions DiffOptions) (map[string]interface{}, error) {
+ patch := map[string]interface{}{}
+
+ // This will be used to build the $retainKeys directive sent in the patch
+ retainKeysList := make([]interface{}, 0, len(modified))
+
+ // Compare each value in the modified map against the value in the original map
+ for key, modifiedValue := range modified {
+ // Get the underlying type for pointers
+ if diffOptions.BuildRetainKeysDirective && modifiedValue != nil {
+ retainKeysList = append(retainKeysList, key)
+ }
+
+ originalValue, ok := original[key]
+ if !ok {
+ // Key was added, so add to patch
+ if !diffOptions.IgnoreChangesAndAdditions {
+ patch[key] = modifiedValue
+ }
+ continue
+ }
+
+ // The patch may have a patch directive
+ // TODO: figure out if we need this. This shouldn't be needed by apply. When would the original map have patch directives in it?
+ foundDirectiveMarker, err := handleDirectiveMarker(key, originalValue, modifiedValue, patch)
+ if err != nil {
+ return nil, err
+ }
+ if foundDirectiveMarker {
+ continue
+ }
+
+ if reflect.TypeOf(originalValue) != reflect.TypeOf(modifiedValue) {
+ // Types have changed, so add to patch
+ if !diffOptions.IgnoreChangesAndAdditions {
+ patch[key] = modifiedValue
+ }
+ continue
+ }
+
+ // Types are the same, so compare values
+ switch originalValueTyped := originalValue.(type) {
+ case map[string]interface{}:
+ modifiedValueTyped := modifiedValue.(map[string]interface{})
+ err = handleMapDiff(key, originalValueTyped, modifiedValueTyped, patch, schema, diffOptions)
+ case []interface{}:
+ modifiedValueTyped := modifiedValue.([]interface{})
+ err = handleSliceDiff(key, originalValueTyped, modifiedValueTyped, patch, schema, diffOptions)
+ default:
+ replacePatchFieldIfNotEqual(key, originalValue, modifiedValue, patch, diffOptions)
+ }
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ updatePatchIfMissing(original, modified, patch, diffOptions)
+ // Insert the retainKeysList iff there are values present in the retainKeysList and
+ // either of the following is true:
+ // - the patch is not empty
+ // - there are additional field in original that need to be cleared
+ if len(retainKeysList) > 0 &&
+ (len(patch) > 0 || hasAdditionalNewField(original, modified)) {
+ patch[retainKeysDirective] = sortScalars(retainKeysList)
+ }
+ return patch, nil
+}
+
+// handleDirectiveMarker handles how to diff directive marker between 2 objects
+func handleDirectiveMarker(key string, originalValue, modifiedValue interface{}, patch map[string]interface{}) (bool, error) {
+ if key == directiveMarker {
+ originalString, ok := originalValue.(string)
+ if !ok {
+ return false, fmt.Errorf("invalid value for special key: %s", directiveMarker)
+ }
+ modifiedString, ok := modifiedValue.(string)
+ if !ok {
+ return false, fmt.Errorf("invalid value for special key: %s", directiveMarker)
+ }
+ if modifiedString != originalString {
+ patch[directiveMarker] = modifiedValue
+ }
+ return true, nil
+ }
+ return false, nil
+}
+
+// handleMapDiff diff between 2 maps `originalValueTyped` and `modifiedValue`,
+// puts the diff in the `patch` associated with `key`
+// key is the key associated with originalValue and modifiedValue.
+// originalValue, modifiedValue are the old and new value respectively.They are both maps
+// patch is the patch map that contains key and the updated value, and it is the parent of originalValue, modifiedValue
+// diffOptions contains multiple options to control how we do the diff.
+func handleMapDiff(key string, originalValue, modifiedValue, patch map[string]interface{},
+ schema LookupPatchMeta, diffOptions DiffOptions) error {
+ subschema, patchMeta, err := schema.LookupPatchMetadataForStruct(key)
+
+ if err != nil {
+ // We couldn't look up metadata for the field
+ // If the values are identical, this doesn't matter, no patch is needed
+ if reflect.DeepEqual(originalValue, modifiedValue) {
+ return nil
+ }
+ // Otherwise, return the error
+ return err
+ }
+ retainKeys, patchStrategy, err := extractRetainKeysPatchStrategy(patchMeta.GetPatchStrategies())
+ if err != nil {
+ return err
+ }
+ diffOptions.BuildRetainKeysDirective = retainKeys
+ switch patchStrategy {
+ // The patch strategic from metadata tells us to replace the entire object instead of diffing it
+ case replaceDirective:
+ if !diffOptions.IgnoreChangesAndAdditions {
+ patch[key] = modifiedValue
+ }
+ default:
+ patchValue, err := diffMaps(originalValue, modifiedValue, subschema, diffOptions)
+ if err != nil {
+ return err
+ }
+ // Maps were not identical, use provided patch value
+ if len(patchValue) > 0 {
+ patch[key] = patchValue
+ }
+ }
+ return nil
+}
+
+// handleSliceDiff diff between 2 slices `originalValueTyped` and `modifiedValue`,
+// puts the diff in the `patch` associated with `key`
+// key is the key associated with originalValue and modifiedValue.
+// originalValue, modifiedValue are the old and new value respectively.They are both slices
+// patch is the patch map that contains key and the updated value, and it is the parent of originalValue, modifiedValue
+// diffOptions contains multiple options to control how we do the diff.
+func handleSliceDiff(key string, originalValue, modifiedValue []interface{}, patch map[string]interface{},
+ schema LookupPatchMeta, diffOptions DiffOptions) error {
+ subschema, patchMeta, err := schema.LookupPatchMetadataForSlice(key)
+ if err != nil {
+ // We couldn't look up metadata for the field
+ // If the values are identical, this doesn't matter, no patch is needed
+ if reflect.DeepEqual(originalValue, modifiedValue) {
+ return nil
+ }
+ // Otherwise, return the error
+ return err
+ }
+ retainKeys, patchStrategy, err := extractRetainKeysPatchStrategy(patchMeta.GetPatchStrategies())
+ if err != nil {
+ return err
+ }
+ switch patchStrategy {
+ // Merge the 2 slices using mergePatchKey
+ case mergeDirective:
+ diffOptions.BuildRetainKeysDirective = retainKeys
+ addList, deletionList, setOrderList, err := diffLists(originalValue, modifiedValue, subschema, patchMeta.GetPatchMergeKey(), diffOptions)
+ if err != nil {
+ return err
+ }
+ if len(addList) > 0 {
+ patch[key] = addList
+ }
+ // generate a parallel list for deletion
+ if len(deletionList) > 0 {
+ parallelDeletionListKey := fmt.Sprintf("%s/%s", deleteFromPrimitiveListDirectivePrefix, key)
+ patch[parallelDeletionListKey] = deletionList
+ }
+ if len(setOrderList) > 0 {
+ parallelSetOrderListKey := fmt.Sprintf("%s/%s", setElementOrderDirectivePrefix, key)
+ patch[parallelSetOrderListKey] = setOrderList
+ }
+ default:
+ replacePatchFieldIfNotEqual(key, originalValue, modifiedValue, patch, diffOptions)
+ }
+ return nil
+}
+
+// replacePatchFieldIfNotEqual updates the patch if original and modified are not deep equal
+// if diffOptions.IgnoreChangesAndAdditions is false.
+// original is the old value, maybe either the live cluster object or the last applied configuration
+// modified is the new value, is always the users new config
+func replacePatchFieldIfNotEqual(key string, original, modified interface{},
+ patch map[string]interface{}, diffOptions DiffOptions) {
+ if diffOptions.IgnoreChangesAndAdditions {
+ // Ignoring changes - do nothing
+ return
+ }
+ if reflect.DeepEqual(original, modified) {
+ // Contents are identical - do nothing
+ return
+ }
+ // Create a patch to replace the old value with the new one
+ patch[key] = modified
+}
+
+// updatePatchIfMissing iterates over `original` when ignoreDeletions is false.
+// Clear the field whose key is not present in `modified`.
+// original is the old value, maybe either the live cluster object or the last applied configuration
+// modified is the new value, is always the users new config
+func updatePatchIfMissing(original, modified, patch map[string]interface{}, diffOptions DiffOptions) {
+ if diffOptions.IgnoreDeletions {
+ // Ignoring deletion - do nothing
+ return
+ }
+ // Add nils for deleted values
+ for key := range original {
+ if _, found := modified[key]; !found {
+ patch[key] = nil
+ }
+ }
+}
+
+// validateMergeKeyInLists checks if each map in the list has the mentryerge key.
+func validateMergeKeyInLists(mergeKey string, lists ...[]interface{}) error {
+ for _, list := range lists {
+ for _, item := range list {
+ m, ok := item.(map[string]interface{})
+ if !ok {
+ return mergepatch.ErrBadArgType(m, item)
+ }
+ if _, ok = m[mergeKey]; !ok {
+ return mergepatch.ErrNoMergeKey(m, mergeKey)
+ }
+ }
+ }
+ return nil
+}
+
+// normalizeElementOrder sort `patch` list by `patchOrder` and sort `serverOnly` list by `serverOrder`.
+// Then it merges the 2 sorted lists.
+// It guarantee the relative order in the patch list and in the serverOnly list is kept.
+// `patch` is a list of items in the patch, and `serverOnly` is a list of items in the live object.
+// `patchOrder` is the order we want `patch` list to have and
+// `serverOrder` is the order we want `serverOnly` list to have.
+// kind is the kind of each item in the lists `patch` and `serverOnly`.
+func normalizeElementOrder(patch, serverOnly, patchOrder, serverOrder []interface{}, mergeKey string, kind reflect.Kind) ([]interface{}, error) {
+ patch, err := normalizeSliceOrder(patch, patchOrder, mergeKey, kind)
+ if err != nil {
+ return nil, err
+ }
+ serverOnly, err = normalizeSliceOrder(serverOnly, serverOrder, mergeKey, kind)
+ if err != nil {
+ return nil, err
+ }
+ all := mergeSortedSlice(serverOnly, patch, serverOrder, mergeKey, kind)
+
+ return all, nil
+}
+
+// mergeSortedSlice merges the 2 sorted lists by serverOrder with best effort.
+// It will insert each item in `left` list to `right` list. In most cases, the 2 lists will be interleaved.
+// The relative order of left and right are guaranteed to be kept.
+// They have higher precedence than the order in the live list.
+// The place for a item in `left` is found by:
+// scan from the place of last insertion in `right` to the end of `right`,
+// the place is before the first item that is greater than the item we want to insert.
+// example usage: using server-only items as left and patch items as right. We insert server-only items
+// to patch list. We use the order of live object as record for comparison.
+func mergeSortedSlice(left, right, serverOrder []interface{}, mergeKey string, kind reflect.Kind) []interface{} {
+ // Returns if l is less than r, and if both have been found.
+ // If l and r both present and l is in front of r, l is less than r.
+ less := func(l, r interface{}) (bool, bool) {
+ li := index(serverOrder, l, mergeKey, kind)
+ ri := index(serverOrder, r, mergeKey, kind)
+ if li >= 0 && ri >= 0 {
+ return li < ri, true
+ } else {
+ return false, false
+ }
+ }
+
+ // left and right should be non-overlapping.
+ size := len(left) + len(right)
+ i, j := 0, 0
+ s := make([]interface{}, size, size)
+
+ for k := 0; k < size; k++ {
+ if i >= len(left) && j < len(right) {
+ // have items left in `right` list
+ s[k] = right[j]
+ j++
+ } else if j >= len(right) && i < len(left) {
+ // have items left in `left` list
+ s[k] = left[i]
+ i++
+ } else {
+ // compare them if i and j are both in bound
+ less, foundBoth := less(left[i], right[j])
+ if foundBoth && less {
+ s[k] = left[i]
+ i++
+ } else {
+ s[k] = right[j]
+ j++
+ }
+ }
+ }
+ return s
+}
+
+// index returns the index of the item in the given items, or -1 if it doesn't exist
+// l must NOT be a slice of slices, this should be checked before calling.
+func index(l []interface{}, valToLookUp interface{}, mergeKey string, kind reflect.Kind) int {
+ var getValFn func(interface{}) interface{}
+ // Get the correct `getValFn` based on item `kind`.
+ // It should return the value of merge key for maps and
+ // return the item for other kinds.
+ switch kind {
+ case reflect.Map:
+ getValFn = func(item interface{}) interface{} {
+ typedItem, ok := item.(map[string]interface{})
+ if !ok {
+ return nil
+ }
+ val := typedItem[mergeKey]
+ return val
+ }
+ default:
+ getValFn = func(item interface{}) interface{} {
+ return item
+ }
+ }
+
+ for i, v := range l {
+ if getValFn(valToLookUp) == getValFn(v) {
+ return i
+ }
+ }
+ return -1
+}
+
+// extractToDeleteItems takes a list and
+// returns 2 lists: one contains items that should be kept and the other contains items to be deleted.
+func extractToDeleteItems(l []interface{}) ([]interface{}, []interface{}, error) {
+ var nonDelete, toDelete []interface{}
+ for _, v := range l {
+ m, ok := v.(map[string]interface{})
+ if !ok {
+ return nil, nil, mergepatch.ErrBadArgType(m, v)
+ }
+
+ directive, foundDirective := m[directiveMarker]
+ if foundDirective && directive == deleteDirective {
+ toDelete = append(toDelete, v)
+ } else {
+ nonDelete = append(nonDelete, v)
+ }
+ }
+ return nonDelete, toDelete, nil
+}
+
+// normalizeSliceOrder sort `toSort` list by `order`
+func normalizeSliceOrder(toSort, order []interface{}, mergeKey string, kind reflect.Kind) ([]interface{}, error) {
+ var toDelete []interface{}
+ if kind == reflect.Map {
+ // make sure each item in toSort, order has merge key
+ err := validateMergeKeyInLists(mergeKey, toSort, order)
+ if err != nil {
+ return nil, err
+ }
+ toSort, toDelete, err = extractToDeleteItems(toSort)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ sort.SliceStable(toSort, func(i, j int) bool {
+ if ii := index(order, toSort[i], mergeKey, kind); ii >= 0 {
+ if ij := index(order, toSort[j], mergeKey, kind); ij >= 0 {
+ return ii < ij
+ }
+ }
+ return true
+ })
+ toSort = append(toSort, toDelete...)
+ return toSort, nil
+}
+
+// Returns a (recursive) strategic merge patch, a parallel deletion list if necessary and
+// another list to set the order of the list
+// Only list of primitives with merge strategy will generate a parallel deletion list.
+// These two lists should yield modified when applied to original, for lists with merge semantics.
+func diffLists(original, modified []interface{}, schema LookupPatchMeta, mergeKey string, diffOptions DiffOptions) ([]interface{}, []interface{}, []interface{}, error) {
+ if len(original) == 0 {
+ // Both slices are empty - do nothing
+ if len(modified) == 0 || diffOptions.IgnoreChangesAndAdditions {
+ return nil, nil, nil, nil
+ }
+
+ // Old slice was empty - add all elements from the new slice
+ return modified, nil, nil, nil
+ }
+
+ elementType, err := sliceElementType(original, modified)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+
+ var patchList, deleteList, setOrderList []interface{}
+ kind := elementType.Kind()
+ switch kind {
+ case reflect.Map:
+ patchList, deleteList, err = diffListsOfMaps(original, modified, schema, mergeKey, diffOptions)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+ patchList, err = normalizeSliceOrder(patchList, modified, mergeKey, kind)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+ orderSame, err := isOrderSame(original, modified, mergeKey)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+ // append the deletions to the end of the patch list.
+ patchList = append(patchList, deleteList...)
+ deleteList = nil
+ // generate the setElementOrder list when there are content changes or order changes
+ if diffOptions.SetElementOrder &&
+ ((!diffOptions.IgnoreChangesAndAdditions && (len(patchList) > 0 || !orderSame)) ||
+ (!diffOptions.IgnoreDeletions && len(patchList) > 0)) {
+ // Generate a list of maps that each item contains only the merge key.
+ setOrderList = make([]interface{}, len(modified))
+ for i, v := range modified {
+ typedV := v.(map[string]interface{})
+ setOrderList[i] = map[string]interface{}{
+ mergeKey: typedV[mergeKey],
+ }
+ }
+ }
+ case reflect.Slice:
+ // Lists of Lists are not permitted by the api
+ return nil, nil, nil, mergepatch.ErrNoListOfLists
+ default:
+ patchList, deleteList, err = diffListsOfScalars(original, modified, diffOptions)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+ patchList, err = normalizeSliceOrder(patchList, modified, mergeKey, kind)
+ // generate the setElementOrder list when there are content changes or order changes
+ if diffOptions.SetElementOrder && ((!diffOptions.IgnoreDeletions && len(deleteList) > 0) ||
+ (!diffOptions.IgnoreChangesAndAdditions && !reflect.DeepEqual(original, modified))) {
+ setOrderList = modified
+ }
+ }
+ return patchList, deleteList, setOrderList, err
+}
+
+// isOrderSame checks if the order in a list has changed
+func isOrderSame(original, modified []interface{}, mergeKey string) (bool, error) {
+ if len(original) != len(modified) {
+ return false, nil
+ }
+ for i, modifiedItem := range modified {
+ equal, err := mergeKeyValueEqual(original[i], modifiedItem, mergeKey)
+ if err != nil || !equal {
+ return equal, err
+ }
+ }
+ return true, nil
+}
+
+// diffListsOfScalars returns 2 lists, the first one is addList and the second one is deletionList.
+// Argument diffOptions.IgnoreChangesAndAdditions controls if calculate addList. true means not calculate.
+// Argument diffOptions.IgnoreDeletions controls if calculate deletionList. true means not calculate.
+// original may be changed, but modified is guaranteed to not be changed
+func diffListsOfScalars(original, modified []interface{}, diffOptions DiffOptions) ([]interface{}, []interface{}, error) {
+ modifiedCopy := make([]interface{}, len(modified))
+ copy(modifiedCopy, modified)
+ // Sort the scalars for easier calculating the diff
+ originalScalars := sortScalars(original)
+ modifiedScalars := sortScalars(modifiedCopy)
+
+ originalIndex, modifiedIndex := 0, 0
+ addList := []interface{}{}
+ deletionList := []interface{}{}
+
+ for {
+ originalInBounds := originalIndex < len(originalScalars)
+ modifiedInBounds := modifiedIndex < len(modifiedScalars)
+ if !originalInBounds && !modifiedInBounds {
+ break
+ }
+ // we need to compare the string representation of the scalar,
+ // because the scalar is an interface which doesn't support either < or >
+ // And that's how func sortScalars compare scalars.
+ var originalString, modifiedString string
+ var originalValue, modifiedValue interface{}
+ if originalInBounds {
+ originalValue = originalScalars[originalIndex]
+ originalString = fmt.Sprintf("%v", originalValue)
+ }
+ if modifiedInBounds {
+ modifiedValue = modifiedScalars[modifiedIndex]
+ modifiedString = fmt.Sprintf("%v", modifiedValue)
+ }
+
+ originalV, modifiedV := compareListValuesAtIndex(originalInBounds, modifiedInBounds, originalString, modifiedString)
+ switch {
+ case originalV == nil && modifiedV == nil:
+ originalIndex++
+ modifiedIndex++
+ case originalV != nil && modifiedV == nil:
+ if !diffOptions.IgnoreDeletions {
+ deletionList = append(deletionList, originalValue)
+ }
+ originalIndex++
+ case originalV == nil && modifiedV != nil:
+ if !diffOptions.IgnoreChangesAndAdditions {
+ addList = append(addList, modifiedValue)
+ }
+ modifiedIndex++
+ default:
+ return nil, nil, fmt.Errorf("Unexpected returned value from compareListValuesAtIndex: %v and %v", originalV, modifiedV)
+ }
+ }
+
+ return addList, deduplicateScalars(deletionList), nil
+}
+
+// If first return value is non-nil, list1 contains an element not present in list2
+// If second return value is non-nil, list2 contains an element not present in list1
+func compareListValuesAtIndex(list1Inbounds, list2Inbounds bool, list1Value, list2Value string) (interface{}, interface{}) {
+ bothInBounds := list1Inbounds && list2Inbounds
+ switch {
+ // scalars are identical
+ case bothInBounds && list1Value == list2Value:
+ return nil, nil
+ // only list2 is in bound
+ case !list1Inbounds:
+ fallthrough
+ // list2 has additional scalar
+ case bothInBounds && list1Value > list2Value:
+ return nil, list2Value
+ // only original is in bound
+ case !list2Inbounds:
+ fallthrough
+ // original has additional scalar
+ case bothInBounds && list1Value < list2Value:
+ return list1Value, nil
+ default:
+ return nil, nil
+ }
+}
+
+// diffListsOfMaps takes a pair of lists and
+// returns a (recursive) strategic merge patch list contains additions and changes and
+// a deletion list contains deletions
+func diffListsOfMaps(original, modified []interface{}, schema LookupPatchMeta, mergeKey string, diffOptions DiffOptions) ([]interface{}, []interface{}, error) {
+ patch := make([]interface{}, 0, len(modified))
+ deletionList := make([]interface{}, 0, len(original))
+
+ originalSorted, err := sortMergeListsByNameArray(original, schema, mergeKey, false)
+ if err != nil {
+ return nil, nil, err
+ }
+ modifiedSorted, err := sortMergeListsByNameArray(modified, schema, mergeKey, false)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ originalIndex, modifiedIndex := 0, 0
+ for {
+ originalInBounds := originalIndex < len(originalSorted)
+ modifiedInBounds := modifiedIndex < len(modifiedSorted)
+ bothInBounds := originalInBounds && modifiedInBounds
+ if !originalInBounds && !modifiedInBounds {
+ break
+ }
+
+ var originalElementMergeKeyValueString, modifiedElementMergeKeyValueString string
+ var originalElementMergeKeyValue, modifiedElementMergeKeyValue interface{}
+ var originalElement, modifiedElement map[string]interface{}
+ if originalInBounds {
+ originalElement, originalElementMergeKeyValue, err = getMapAndMergeKeyValueByIndex(originalIndex, mergeKey, originalSorted)
+ if err != nil {
+ return nil, nil, err
+ }
+ originalElementMergeKeyValueString = fmt.Sprintf("%v", originalElementMergeKeyValue)
+ }
+ if modifiedInBounds {
+ modifiedElement, modifiedElementMergeKeyValue, err = getMapAndMergeKeyValueByIndex(modifiedIndex, mergeKey, modifiedSorted)
+ if err != nil {
+ return nil, nil, err
+ }
+ modifiedElementMergeKeyValueString = fmt.Sprintf("%v", modifiedElementMergeKeyValue)
+ }
+
+ switch {
+ case bothInBounds && ItemMatchesOriginalAndModifiedSlice(originalElementMergeKeyValueString, modifiedElementMergeKeyValueString):
+ // Merge key values are equal, so recurse
+ patchValue, err := diffMaps(originalElement, modifiedElement, schema, diffOptions)
+ if err != nil {
+ return nil, nil, err
+ }
+ if len(patchValue) > 0 {
+ patchValue[mergeKey] = modifiedElementMergeKeyValue
+ patch = append(patch, patchValue)
+ }
+ originalIndex++
+ modifiedIndex++
+ // only modified is in bound
+ case !originalInBounds:
+ fallthrough
+ // modified has additional map
+ case bothInBounds && ItemAddedToModifiedSlice(originalElementMergeKeyValueString, modifiedElementMergeKeyValueString):
+ if !diffOptions.IgnoreChangesAndAdditions {
+ patch = append(patch, modifiedElement)
+ }
+ modifiedIndex++
+ // only original is in bound
+ case !modifiedInBounds:
+ fallthrough
+ // original has additional map
+ case bothInBounds && ItemRemovedFromModifiedSlice(originalElementMergeKeyValueString, modifiedElementMergeKeyValueString):
+ if !diffOptions.IgnoreDeletions {
+ // Item was deleted, so add delete directive
+ deletionList = append(deletionList, CreateDeleteDirective(mergeKey, originalElementMergeKeyValue))
+ }
+ originalIndex++
+ }
+ }
+
+ return patch, deletionList, nil
+}
+
+// getMapAndMergeKeyValueByIndex return a map in the list and its merge key value given the index of the map.
+func getMapAndMergeKeyValueByIndex(index int, mergeKey string, listOfMaps []interface{}) (map[string]interface{}, interface{}, error) {
+ m, ok := listOfMaps[index].(map[string]interface{})
+ if !ok {
+ return nil, nil, mergepatch.ErrBadArgType(m, listOfMaps[index])
+ }
+
+ val, ok := m[mergeKey]
+ if !ok {
+ return nil, nil, mergepatch.ErrNoMergeKey(m, mergeKey)
+ }
+ return m, val, nil
+}
+
+// StrategicMergePatch applies a strategic merge patch. The patch and the original document
+// must be json encoded content. A patch can be created from an original and a modified document
+// by calling CreateStrategicMergePatch.
+func StrategicMergePatch(original, patch []byte, dataStruct interface{}) ([]byte, error) {
+ schema, err := NewPatchMetaFromStruct(dataStruct)
+ if err != nil {
+ return nil, err
+ }
+
+ return StrategicMergePatchUsingLookupPatchMeta(original, patch, schema)
+}
+
+func StrategicMergePatchUsingLookupPatchMeta(original, patch []byte, schema LookupPatchMeta) ([]byte, error) {
+ originalMap, err := handleUnmarshal(original)
+ if err != nil {
+ return nil, err
+ }
+ patchMap, err := handleUnmarshal(patch)
+ if err != nil {
+ return nil, err
+ }
+
+ result, err := StrategicMergeMapPatchUsingLookupPatchMeta(originalMap, patchMap, schema)
+ if err != nil {
+ return nil, err
+ }
+
+ return json.Marshal(result)
+}
+
+func handleUnmarshal(j []byte) (map[string]interface{}, error) {
+ if j == nil {
+ j = []byte("{}")
+ }
+
+ m := map[string]interface{}{}
+ err := json.Unmarshal(j, &m)
+ if err != nil {
+ return nil, mergepatch.ErrBadJSONDoc
+ }
+ return m, nil
+}
+
+// StrategicMergeMapPatch applies a strategic merge patch. The original and patch documents
+// must be JSONMap. A patch can be created from an original and modified document by
+// calling CreateTwoWayMergeMapPatch.
+// Warning: the original and patch JSONMap objects are mutated by this function and should not be reused.
+func StrategicMergeMapPatch(original, patch JSONMap, dataStruct interface{}) (JSONMap, error) {
+ schema, err := NewPatchMetaFromStruct(dataStruct)
+ if err != nil {
+ return nil, err
+ }
+
+ // We need the go struct tags `patchMergeKey` and `patchStrategy` for fields that support a strategic merge patch.
+ // For native resources, we can easily figure out these tags since we know the fields.
+
+ // Because custom resources are decoded as Unstructured and because we're missing the metadata about how to handle
+ // each field in a strategic merge patch, we can't find the go struct tags. Hence, we can't easily do a strategic merge
+ // for custom resources. So we should fail fast and return an error.
+ if _, ok := dataStruct.(*unstructured.Unstructured); ok {
+ return nil, mergepatch.ErrUnsupportedStrategicMergePatchFormat
+ }
+
+ return StrategicMergeMapPatchUsingLookupPatchMeta(original, patch, schema)
+}
+
+func StrategicMergeMapPatchUsingLookupPatchMeta(original, patch JSONMap, schema LookupPatchMeta) (JSONMap, error) {
+ mergeOptions := MergeOptions{
+ MergeParallelList: true,
+ IgnoreUnmatchedNulls: true,
+ }
+ return mergeMap(original, patch, schema, mergeOptions)
+}
+
+// MergeStrategicMergeMapPatchUsingLookupPatchMeta merges strategic merge
+// patches retaining `null` fields and parallel lists. If 2 patches change the
+// same fields and the latter one will override the former one. If you don't
+// want that happen, you need to run func MergingMapsHaveConflicts before
+// merging these patches. Applying the resulting merged merge patch to a JSONMap
+// yields the same as merging each strategic merge patch to the JSONMap in
+// succession.
+func MergeStrategicMergeMapPatchUsingLookupPatchMeta(schema LookupPatchMeta, patches ...JSONMap) (JSONMap, error) {
+ mergeOptions := MergeOptions{
+ MergeParallelList: false,
+ IgnoreUnmatchedNulls: false,
+ }
+ merged := JSONMap{}
+ var err error
+ for _, patch := range patches {
+ merged, err = mergeMap(merged, patch, schema, mergeOptions)
+ if err != nil {
+ return nil, err
+ }
+ }
+ return merged, nil
+}
+
+// handleDirectiveInMergeMap handles the patch directive when merging 2 maps.
+func handleDirectiveInMergeMap(directive interface{}, patch map[string]interface{}) (map[string]interface{}, error) {
+ if directive == replaceDirective {
+ // If the patch contains "$patch: replace", don't merge it, just use the
+ // patch directly. Later on, we can add a single level replace that only
+ // affects the map that the $patch is in.
+ delete(patch, directiveMarker)
+ return patch, nil
+ }
+
+ if directive == deleteDirective {
+ // If the patch contains "$patch: delete", don't merge it, just return
+ // an empty map.
+ return map[string]interface{}{}, nil
+ }
+
+ return nil, mergepatch.ErrBadPatchType(directive, patch)
+}
+
+func containsDirectiveMarker(item interface{}) bool {
+ m, ok := item.(map[string]interface{})
+ if ok {
+ if _, foundDirectiveMarker := m[directiveMarker]; foundDirectiveMarker {
+ return true
+ }
+ }
+ return false
+}
+
+func mergeKeyValueEqual(left, right interface{}, mergeKey string) (bool, error) {
+ if len(mergeKey) == 0 {
+ return left == right, nil
+ }
+ typedLeft, ok := left.(map[string]interface{})
+ if !ok {
+ return false, mergepatch.ErrBadArgType(typedLeft, left)
+ }
+ typedRight, ok := right.(map[string]interface{})
+ if !ok {
+ return false, mergepatch.ErrBadArgType(typedRight, right)
+ }
+ mergeKeyLeft, ok := typedLeft[mergeKey]
+ if !ok {
+ return false, mergepatch.ErrNoMergeKey(typedLeft, mergeKey)
+ }
+ mergeKeyRight, ok := typedRight[mergeKey]
+ if !ok {
+ return false, mergepatch.ErrNoMergeKey(typedRight, mergeKey)
+ }
+ return mergeKeyLeft == mergeKeyRight, nil
+}
+
+// extractKey trims the prefix and return the original key
+func extractKey(s, prefix string) (string, error) {
+ substrings := strings.SplitN(s, "/", 2)
+ if len(substrings) <= 1 || substrings[0] != prefix {
+ switch prefix {
+ case deleteFromPrimitiveListDirectivePrefix:
+ return "", mergepatch.ErrBadPatchFormatForPrimitiveList
+ case setElementOrderDirectivePrefix:
+ return "", mergepatch.ErrBadPatchFormatForSetElementOrderList
+ default:
+ return "", fmt.Errorf("fail to find unknown prefix %q in %s\n", prefix, s)
+ }
+ }
+ return substrings[1], nil
+}
+
+// validatePatchUsingSetOrderList verifies:
+// the relative order of any two items in the setOrderList list matches that in the patch list.
+// the items in the patch list must be a subset or the same as the $setElementOrder list (deletions are ignored).
+func validatePatchWithSetOrderList(patchList, setOrderList interface{}, mergeKey string) error {
+ typedSetOrderList, ok := setOrderList.([]interface{})
+ if !ok {
+ return mergepatch.ErrBadPatchFormatForSetElementOrderList
+ }
+ typedPatchList, ok := patchList.([]interface{})
+ if !ok {
+ return mergepatch.ErrBadPatchFormatForSetElementOrderList
+ }
+ if len(typedSetOrderList) == 0 || len(typedPatchList) == 0 {
+ return nil
+ }
+
+ var nonDeleteList, toDeleteList []interface{}
+ var err error
+ if len(mergeKey) > 0 {
+ nonDeleteList, toDeleteList, err = extractToDeleteItems(typedPatchList)
+ if err != nil {
+ return err
+ }
+ } else {
+ nonDeleteList = typedPatchList
+ }
+
+ patchIndex, setOrderIndex := 0, 0
+ for patchIndex < len(nonDeleteList) && setOrderIndex < len(typedSetOrderList) {
+ if containsDirectiveMarker(nonDeleteList[patchIndex]) {
+ patchIndex++
+ continue
+ }
+ mergeKeyEqual, err := mergeKeyValueEqual(nonDeleteList[patchIndex], typedSetOrderList[setOrderIndex], mergeKey)
+ if err != nil {
+ return err
+ }
+ if mergeKeyEqual {
+ patchIndex++
+ }
+ setOrderIndex++
+ }
+ // If patchIndex is inbound but setOrderIndex if out of bound mean there are items mismatching between the patch list and setElementOrder list.
+ // the second check is is a sanity check, and should always be true if the first is true.
+ if patchIndex < len(nonDeleteList) && setOrderIndex >= len(typedSetOrderList) {
+ return fmt.Errorf("The order in patch list:\n%v\n doesn't match %s list:\n%v\n", typedPatchList, setElementOrderDirectivePrefix, setOrderList)
+ }
+ typedPatchList = append(nonDeleteList, toDeleteList...)
+ return nil
+}
+
+// preprocessDeletionListForMerging preprocesses the deletion list.
+// it returns shouldContinue, isDeletionList, noPrefixKey
+func preprocessDeletionListForMerging(key string, original map[string]interface{},
+ patchVal interface{}, mergeDeletionList bool) (bool, bool, string, error) {
+ // If found a parallel list for deletion and we are going to merge the list,
+ // overwrite the key to the original key and set flag isDeleteList
+ foundParallelListPrefix := strings.HasPrefix(key, deleteFromPrimitiveListDirectivePrefix)
+ if foundParallelListPrefix {
+ if !mergeDeletionList {
+ original[key] = patchVal
+ return true, false, "", nil
+ }
+ originalKey, err := extractKey(key, deleteFromPrimitiveListDirectivePrefix)
+ return false, true, originalKey, err
+ }
+ return false, false, "", nil
+}
+
+// applyRetainKeysDirective looks for a retainKeys directive and applies to original
+// - if no directive exists do nothing
+// - if directive is found, clear keys in original missing from the directive list
+// - validate that all keys present in the patch are present in the retainKeys directive
+// note: original may be another patch request, e.g. applying the add+modified patch to the deletions patch. In this case it may have directives
+func applyRetainKeysDirective(original, patch map[string]interface{}, options MergeOptions) error {
+ retainKeysInPatch, foundInPatch := patch[retainKeysDirective]
+ if !foundInPatch {
+ return nil
+ }
+ // cleanup the directive
+ delete(patch, retainKeysDirective)
+
+ if !options.MergeParallelList {
+ // If original is actually a patch, make sure the retainKeys directives are the same in both patches if present in both.
+ // If not present in the original patch, copy from the modified patch.
+ retainKeysInOriginal, foundInOriginal := original[retainKeysDirective]
+ if foundInOriginal {
+ if !reflect.DeepEqual(retainKeysInOriginal, retainKeysInPatch) {
+ // This error actually should never happen.
+ return fmt.Errorf("%v and %v are not deep equal: this may happen when calculating the 3-way diff patch", retainKeysInOriginal, retainKeysInPatch)
+ }
+ } else {
+ original[retainKeysDirective] = retainKeysInPatch
+ }
+ return nil
+ }
+
+ retainKeysList, ok := retainKeysInPatch.([]interface{})
+ if !ok {
+ return mergepatch.ErrBadPatchFormatForRetainKeys
+ }
+
+ // validate patch to make sure all fields in the patch are present in the retainKeysList.
+ // The map is used only as a set, the value is never referenced
+ m := map[interface{}]struct{}{}
+ for _, v := range retainKeysList {
+ m[v] = struct{}{}
+ }
+ for k, v := range patch {
+ if v == nil || strings.HasPrefix(k, deleteFromPrimitiveListDirectivePrefix) ||
+ strings.HasPrefix(k, setElementOrderDirectivePrefix) {
+ continue
+ }
+ // If there is an item present in the patch but not in the retainKeys list,
+ // the patch is invalid.
+ if _, found := m[k]; !found {
+ return mergepatch.ErrBadPatchFormatForRetainKeys
+ }
+ }
+
+ // clear not present fields
+ for k := range original {
+ if _, found := m[k]; !found {
+ delete(original, k)
+ }
+ }
+ return nil
+}
+
+// mergePatchIntoOriginal processes $setElementOrder list.
+// When not merging the directive, it will make sure $setElementOrder list exist only in original.
+// When merging the directive, it will try to find the $setElementOrder list and
+// its corresponding patch list, validate it and merge it.
+// Then, sort them by the relative order in setElementOrder, patch list and live list.
+// The precedence is $setElementOrder > order in patch list > order in live list.
+// This function will delete the item after merging it to prevent process it again in the future.
+// Ref: https://git.k8s.io/community/contributors/design-proposals/cli/preserve-order-in-strategic-merge-patch.md
+func mergePatchIntoOriginal(original, patch map[string]interface{}, schema LookupPatchMeta, mergeOptions MergeOptions) error {
+ for key, patchV := range patch {
+ // Do nothing if there is no ordering directive
+ if !strings.HasPrefix(key, setElementOrderDirectivePrefix) {
+ continue
+ }
+
+ setElementOrderInPatch := patchV
+ // Copies directive from the second patch (`patch`) to the first patch (`original`)
+ // and checks they are equal and delete the directive in the second patch
+ if !mergeOptions.MergeParallelList {
+ setElementOrderListInOriginal, ok := original[key]
+ if ok {
+ // check if the setElementOrder list in original and the one in patch matches
+ if !reflect.DeepEqual(setElementOrderListInOriginal, setElementOrderInPatch) {
+ return mergepatch.ErrBadPatchFormatForSetElementOrderList
+ }
+ } else {
+ // move the setElementOrder list from patch to original
+ original[key] = setElementOrderInPatch
+ }
+ }
+ delete(patch, key)
+
+ var (
+ ok bool
+ originalFieldValue, patchFieldValue, merged []interface{}
+ patchStrategy string
+ patchMeta PatchMeta
+ subschema LookupPatchMeta
+ )
+ typedSetElementOrderList, ok := setElementOrderInPatch.([]interface{})
+ if !ok {
+ return mergepatch.ErrBadArgType(typedSetElementOrderList, setElementOrderInPatch)
+ }
+ // Trim the setElementOrderDirectivePrefix to get the key of the list field in original.
+ originalKey, err := extractKey(key, setElementOrderDirectivePrefix)
+ if err != nil {
+ return err
+ }
+ // try to find the list with `originalKey` in `original` and `modified` and merge them.
+ originalList, foundOriginal := original[originalKey]
+ patchList, foundPatch := patch[originalKey]
+ if foundOriginal {
+ originalFieldValue, ok = originalList.([]interface{})
+ if !ok {
+ return mergepatch.ErrBadArgType(originalFieldValue, originalList)
+ }
+ }
+ if foundPatch {
+ patchFieldValue, ok = patchList.([]interface{})
+ if !ok {
+ return mergepatch.ErrBadArgType(patchFieldValue, patchList)
+ }
+ }
+ subschema, patchMeta, err = schema.LookupPatchMetadataForSlice(originalKey)
+ if err != nil {
+ return err
+ }
+ _, patchStrategy, err = extractRetainKeysPatchStrategy(patchMeta.GetPatchStrategies())
+ if err != nil {
+ return err
+ }
+ // Check for consistency between the element order list and the field it applies to
+ err = validatePatchWithSetOrderList(patchFieldValue, typedSetElementOrderList, patchMeta.GetPatchMergeKey())
+ if err != nil {
+ return err
+ }
+
+ switch {
+ case foundOriginal && !foundPatch:
+ // no change to list contents
+ merged = originalFieldValue
+ case !foundOriginal && foundPatch:
+ // list was added
+ merged = patchFieldValue
+ case foundOriginal && foundPatch:
+ merged, err = mergeSliceHandler(originalList, patchList, subschema,
+ patchStrategy, patchMeta.GetPatchMergeKey(), false, mergeOptions)
+ if err != nil {
+ return err
+ }
+ case !foundOriginal && !foundPatch:
+ continue
+ }
+
+ // Split all items into patch items and server-only items and then enforce the order.
+ var patchItems, serverOnlyItems []interface{}
+ if len(patchMeta.GetPatchMergeKey()) == 0 {
+ // Primitives doesn't need merge key to do partitioning.
+ patchItems, serverOnlyItems = partitionPrimitivesByPresentInList(merged, typedSetElementOrderList)
+
+ } else {
+ // Maps need merge key to do partitioning.
+ patchItems, serverOnlyItems, err = partitionMapsByPresentInList(merged, typedSetElementOrderList, patchMeta.GetPatchMergeKey())
+ if err != nil {
+ return err
+ }
+ }
+
+ elementType, err := sliceElementType(originalFieldValue, patchFieldValue)
+ if err != nil {
+ return err
+ }
+ kind := elementType.Kind()
+ // normalize merged list
+ // typedSetElementOrderList contains all the relative order in typedPatchList,
+ // so don't need to use typedPatchList
+ both, err := normalizeElementOrder(patchItems, serverOnlyItems, typedSetElementOrderList, originalFieldValue, patchMeta.GetPatchMergeKey(), kind)
+ if err != nil {
+ return err
+ }
+ original[originalKey] = both
+ // delete patch list from patch to prevent process again in the future
+ delete(patch, originalKey)
+ }
+ return nil
+}
+
+// partitionPrimitivesByPresentInList partitions elements into 2 slices, the first containing items present in partitionBy, the other not.
+func partitionPrimitivesByPresentInList(original, partitionBy []interface{}) ([]interface{}, []interface{}) {
+ patch := make([]interface{}, 0, len(original))
+ serverOnly := make([]interface{}, 0, len(original))
+ inPatch := map[interface{}]bool{}
+ for _, v := range partitionBy {
+ inPatch[v] = true
+ }
+ for _, v := range original {
+ if !inPatch[v] {
+ serverOnly = append(serverOnly, v)
+ } else {
+ patch = append(patch, v)
+ }
+ }
+ return patch, serverOnly
+}
+
+// partitionMapsByPresentInList partitions elements into 2 slices, the first containing items present in partitionBy, the other not.
+func partitionMapsByPresentInList(original, partitionBy []interface{}, mergeKey string) ([]interface{}, []interface{}, error) {
+ patch := make([]interface{}, 0, len(original))
+ serverOnly := make([]interface{}, 0, len(original))
+ for _, v := range original {
+ typedV, ok := v.(map[string]interface{})
+ if !ok {
+ return nil, nil, mergepatch.ErrBadArgType(typedV, v)
+ }
+ mergeKeyValue, foundMergeKey := typedV[mergeKey]
+ if !foundMergeKey {
+ return nil, nil, mergepatch.ErrNoMergeKey(typedV, mergeKey)
+ }
+ _, _, found, err := findMapInSliceBasedOnKeyValue(partitionBy, mergeKey, mergeKeyValue)
+ if err != nil {
+ return nil, nil, err
+ }
+ if !found {
+ serverOnly = append(serverOnly, v)
+ } else {
+ patch = append(patch, v)
+ }
+ }
+ return patch, serverOnly, nil
+}
+
+// Merge fields from a patch map into the original map. Note: This may modify
+// both the original map and the patch because getting a deep copy of a map in
+// golang is highly non-trivial.
+// flag mergeOptions.MergeParallelList controls if using the parallel list to delete or keeping the list.
+// If patch contains any null field (e.g. field_1: null) that is not
+// present in original, then to propagate it to the end result use
+// mergeOptions.IgnoreUnmatchedNulls == false.
+func mergeMap(original, patch map[string]interface{}, schema LookupPatchMeta, mergeOptions MergeOptions) (map[string]interface{}, error) {
+ if v, ok := patch[directiveMarker]; ok {
+ return handleDirectiveInMergeMap(v, patch)
+ }
+
+ // nil is an accepted value for original to simplify logic in other places.
+ // If original is nil, replace it with an empty map and then apply the patch.
+ if original == nil {
+ original = map[string]interface{}{}
+ }
+
+ err := applyRetainKeysDirective(original, patch, mergeOptions)
+ if err != nil {
+ return nil, err
+ }
+
+ // Process $setElementOrder list and other lists sharing the same key.
+ // When not merging the directive, it will make sure $setElementOrder list exist only in original.
+ // When merging the directive, it will process $setElementOrder and its patch list together.
+ // This function will delete the merged elements from patch so they will not be reprocessed
+ err = mergePatchIntoOriginal(original, patch, schema, mergeOptions)
+ if err != nil {
+ return nil, err
+ }
+
+ // Start merging the patch into the original.
+ for k, patchV := range patch {
+ skipProcessing, isDeleteList, noPrefixKey, err := preprocessDeletionListForMerging(k, original, patchV, mergeOptions.MergeParallelList)
+ if err != nil {
+ return nil, err
+ }
+ if skipProcessing {
+ continue
+ }
+ if len(noPrefixKey) > 0 {
+ k = noPrefixKey
+ }
+
+ // If the value of this key is null, delete the key if it exists in the
+ // original. Otherwise, check if we want to preserve it or skip it.
+ // Preserving the null value is useful when we want to send an explicit
+ // delete to the API server.
+ if patchV == nil {
+ if _, ok := original[k]; ok {
+ delete(original, k)
+ }
+ if mergeOptions.IgnoreUnmatchedNulls {
+ continue
+ }
+ }
+
+ _, ok := original[k]
+ if !ok {
+ // If it's not in the original document, just take the patch value.
+ original[k] = patchV
+ continue
+ }
+
+ originalType := reflect.TypeOf(original[k])
+ patchType := reflect.TypeOf(patchV)
+ if originalType != patchType {
+ original[k] = patchV
+ continue
+ }
+ // If they're both maps or lists, recurse into the value.
+ switch originalType.Kind() {
+ case reflect.Map:
+ subschema, patchMeta, err2 := schema.LookupPatchMetadataForStruct(k)
+ if err2 != nil {
+ return nil, err2
+ }
+ _, patchStrategy, err2 := extractRetainKeysPatchStrategy(patchMeta.GetPatchStrategies())
+ if err2 != nil {
+ return nil, err2
+ }
+ original[k], err = mergeMapHandler(original[k], patchV, subschema, patchStrategy, mergeOptions)
+ case reflect.Slice:
+ subschema, patchMeta, err2 := schema.LookupPatchMetadataForSlice(k)
+ if err2 != nil {
+ return nil, err2
+ }
+ _, patchStrategy, err2 := extractRetainKeysPatchStrategy(patchMeta.GetPatchStrategies())
+ if err2 != nil {
+ return nil, err2
+ }
+ original[k], err = mergeSliceHandler(original[k], patchV, subschema, patchStrategy, patchMeta.GetPatchMergeKey(), isDeleteList, mergeOptions)
+ default:
+ original[k] = patchV
+ }
+ if err != nil {
+ return nil, err
+ }
+ }
+ return original, nil
+}
+
+// mergeMapHandler handles how to merge `patchV` whose key is `key` with `original` respecting
+// fieldPatchStrategy and mergeOptions.
+func mergeMapHandler(original, patch interface{}, schema LookupPatchMeta,
+ fieldPatchStrategy string, mergeOptions MergeOptions) (map[string]interface{}, error) {
+ typedOriginal, typedPatch, err := mapTypeAssertion(original, patch)
+ if err != nil {
+ return nil, err
+ }
+
+ if fieldPatchStrategy != replaceDirective {
+ return mergeMap(typedOriginal, typedPatch, schema, mergeOptions)
+ } else {
+ return typedPatch, nil
+ }
+}
+
+// mergeSliceHandler handles how to merge `patchV` whose key is `key` with `original` respecting
+// fieldPatchStrategy, fieldPatchMergeKey, isDeleteList and mergeOptions.
+func mergeSliceHandler(original, patch interface{}, schema LookupPatchMeta,
+ fieldPatchStrategy, fieldPatchMergeKey string, isDeleteList bool, mergeOptions MergeOptions) ([]interface{}, error) {
+ typedOriginal, typedPatch, err := sliceTypeAssertion(original, patch)
+ if err != nil {
+ return nil, err
+ }
+
+ if fieldPatchStrategy == mergeDirective {
+ return mergeSlice(typedOriginal, typedPatch, schema, fieldPatchMergeKey, mergeOptions, isDeleteList)
+ } else {
+ return typedPatch, nil
+ }
+}
+
+// Merge two slices together. Note: This may modify both the original slice and
+// the patch because getting a deep copy of a slice in golang is highly
+// non-trivial.
+func mergeSlice(original, patch []interface{}, schema LookupPatchMeta, mergeKey string, mergeOptions MergeOptions, isDeleteList bool) ([]interface{}, error) {
+ if len(original) == 0 && len(patch) == 0 {
+ return original, nil
+ }
+
+ // All the values must be of the same type, but not a list.
+ t, err := sliceElementType(original, patch)
+ if err != nil {
+ return nil, err
+ }
+
+ var merged []interface{}
+ kind := t.Kind()
+ // If the elements are not maps, merge the slices of scalars.
+ if kind != reflect.Map {
+ if mergeOptions.MergeParallelList && isDeleteList {
+ return deleteFromSlice(original, patch), nil
+ }
+ // Maybe in the future add a "concat" mode that doesn't
+ // deduplicate.
+ both := append(original, patch...)
+ merged = deduplicateScalars(both)
+
+ } else {
+ if mergeKey == "" {
+ return nil, fmt.Errorf("cannot merge lists without merge key for %s", schema.Name())
+ }
+
+ original, patch, err = mergeSliceWithSpecialElements(original, patch, mergeKey)
+ if err != nil {
+ return nil, err
+ }
+
+ merged, err = mergeSliceWithoutSpecialElements(original, patch, mergeKey, schema, mergeOptions)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ // enforce the order
+ var patchItems, serverOnlyItems []interface{}
+ if len(mergeKey) == 0 {
+ patchItems, serverOnlyItems = partitionPrimitivesByPresentInList(merged, patch)
+ } else {
+ patchItems, serverOnlyItems, err = partitionMapsByPresentInList(merged, patch, mergeKey)
+ if err != nil {
+ return nil, err
+ }
+ }
+ return normalizeElementOrder(patchItems, serverOnlyItems, patch, original, mergeKey, kind)
+}
+
+// mergeSliceWithSpecialElements handles special elements with directiveMarker
+// before merging the slices. It returns a updated `original` and a patch without special elements.
+// original and patch must be slices of maps, they should be checked before calling this function.
+func mergeSliceWithSpecialElements(original, patch []interface{}, mergeKey string) ([]interface{}, []interface{}, error) {
+ patchWithoutSpecialElements := []interface{}{}
+ replace := false
+ for _, v := range patch {
+ typedV := v.(map[string]interface{})
+ patchType, ok := typedV[directiveMarker]
+ if !ok {
+ patchWithoutSpecialElements = append(patchWithoutSpecialElements, v)
+ } else {
+ switch patchType {
+ case deleteDirective:
+ mergeValue, ok := typedV[mergeKey]
+ if ok {
+ var err error
+ original, err = deleteMatchingEntries(original, mergeKey, mergeValue)
+ if err != nil {
+ return nil, nil, err
+ }
+ } else {
+ return nil, nil, mergepatch.ErrNoMergeKey(typedV, mergeKey)
+ }
+ case replaceDirective:
+ replace = true
+ // Continue iterating through the array to prune any other $patch elements.
+ case mergeDirective:
+ return nil, nil, fmt.Errorf("merging lists cannot yet be specified in the patch")
+ default:
+ return nil, nil, mergepatch.ErrBadPatchType(patchType, typedV)
+ }
+ }
+ }
+ if replace {
+ return patchWithoutSpecialElements, nil, nil
+ }
+ return original, patchWithoutSpecialElements, nil
+}
+
+// delete all matching entries (based on merge key) from a merging list
+func deleteMatchingEntries(original []interface{}, mergeKey string, mergeValue interface{}) ([]interface{}, error) {
+ for {
+ _, originalKey, found, err := findMapInSliceBasedOnKeyValue(original, mergeKey, mergeValue)
+ if err != nil {
+ return nil, err
+ }
+
+ if !found {
+ break
+ }
+ // Delete the element at originalKey.
+ original = append(original[:originalKey], original[originalKey+1:]...)
+ }
+ return original, nil
+}
+
+// mergeSliceWithoutSpecialElements merges slices with non-special elements.
+// original and patch must be slices of maps, they should be checked before calling this function.
+func mergeSliceWithoutSpecialElements(original, patch []interface{}, mergeKey string, schema LookupPatchMeta, mergeOptions MergeOptions) ([]interface{}, error) {
+ for _, v := range patch {
+ typedV := v.(map[string]interface{})
+ mergeValue, ok := typedV[mergeKey]
+ if !ok {
+ return nil, mergepatch.ErrNoMergeKey(typedV, mergeKey)
+ }
+
+ // If we find a value with this merge key value in original, merge the
+ // maps. Otherwise append onto original.
+ originalMap, originalKey, found, err := findMapInSliceBasedOnKeyValue(original, mergeKey, mergeValue)
+ if err != nil {
+ return nil, err
+ }
+
+ if found {
+ var mergedMaps interface{}
+ var err error
+ // Merge into original.
+ mergedMaps, err = mergeMap(originalMap, typedV, schema, mergeOptions)
+ if err != nil {
+ return nil, err
+ }
+
+ original[originalKey] = mergedMaps
+ } else {
+ original = append(original, v)
+ }
+ }
+ return original, nil
+}
+
+// deleteFromSlice uses the parallel list to delete the items in a list of scalars
+func deleteFromSlice(current, toDelete []interface{}) []interface{} {
+ toDeleteMap := map[interface{}]interface{}{}
+ processed := make([]interface{}, 0, len(current))
+ for _, v := range toDelete {
+ toDeleteMap[v] = true
+ }
+ for _, v := range current {
+ if _, found := toDeleteMap[v]; !found {
+ processed = append(processed, v)
+ }
+ }
+ return processed
+}
+
+// This method no longer panics if any element of the slice is not a map.
+func findMapInSliceBasedOnKeyValue(m []interface{}, key string, value interface{}) (map[string]interface{}, int, bool, error) {
+ for k, v := range m {
+ typedV, ok := v.(map[string]interface{})
+ if !ok {
+ return nil, 0, false, fmt.Errorf("value for key %v is not a map", k)
+ }
+
+ valueToMatch, ok := typedV[key]
+ if ok && valueToMatch == value {
+ return typedV, k, true, nil
+ }
+ }
+
+ return nil, 0, false, nil
+}
+
+// This function takes a JSON map and sorts all the lists that should be merged
+// by key. This is needed by tests because in JSON, list order is significant,
+// but in Strategic Merge Patch, merge lists do not have significant order.
+// Sorting the lists allows for order-insensitive comparison of patched maps.
+func sortMergeListsByName(mapJSON []byte, schema LookupPatchMeta) ([]byte, error) {
+ var m map[string]interface{}
+ err := json.Unmarshal(mapJSON, &m)
+ if err != nil {
+ return nil, mergepatch.ErrBadJSONDoc
+ }
+
+ newM, err := sortMergeListsByNameMap(m, schema)
+ if err != nil {
+ return nil, err
+ }
+
+ return json.Marshal(newM)
+}
+
+// Function sortMergeListsByNameMap recursively sorts the merge lists by its mergeKey in a map.
+func sortMergeListsByNameMap(s map[string]interface{}, schema LookupPatchMeta) (map[string]interface{}, error) {
+ newS := map[string]interface{}{}
+ for k, v := range s {
+ if k == retainKeysDirective {
+ typedV, ok := v.([]interface{})
+ if !ok {
+ return nil, mergepatch.ErrBadPatchFormatForRetainKeys
+ }
+ v = sortScalars(typedV)
+ } else if strings.HasPrefix(k, deleteFromPrimitiveListDirectivePrefix) {
+ typedV, ok := v.([]interface{})
+ if !ok {
+ return nil, mergepatch.ErrBadPatchFormatForPrimitiveList
+ }
+ v = sortScalars(typedV)
+ } else if strings.HasPrefix(k, setElementOrderDirectivePrefix) {
+ _, ok := v.([]interface{})
+ if !ok {
+ return nil, mergepatch.ErrBadPatchFormatForSetElementOrderList
+ }
+ } else if k != directiveMarker {
+ // recurse for map and slice.
+ switch typedV := v.(type) {
+ case map[string]interface{}:
+ subschema, _, err := schema.LookupPatchMetadataForStruct(k)
+ if err != nil {
+ return nil, err
+ }
+ v, err = sortMergeListsByNameMap(typedV, subschema)
+ if err != nil {
+ return nil, err
+ }
+ case []interface{}:
+ subschema, patchMeta, err := schema.LookupPatchMetadataForSlice(k)
+ if err != nil {
+ return nil, err
+ }
+ _, patchStrategy, err := extractRetainKeysPatchStrategy(patchMeta.GetPatchStrategies())
+ if err != nil {
+ return nil, err
+ }
+ if patchStrategy == mergeDirective {
+ var err error
+ v, err = sortMergeListsByNameArray(typedV, subschema, patchMeta.GetPatchMergeKey(), true)
+ if err != nil {
+ return nil, err
+ }
+ }
+ }
+ }
+
+ newS[k] = v
+ }
+
+ return newS, nil
+}
+
+// Function sortMergeListsByNameMap recursively sorts the merge lists by its mergeKey in an array.
+func sortMergeListsByNameArray(s []interface{}, schema LookupPatchMeta, mergeKey string, recurse bool) ([]interface{}, error) {
+ if len(s) == 0 {
+ return s, nil
+ }
+
+ // We don't support lists of lists yet.
+ t, err := sliceElementType(s)
+ if err != nil {
+ return nil, err
+ }
+
+ // If the elements are not maps...
+ if t.Kind() != reflect.Map {
+ // Sort the elements, because they may have been merged out of order.
+ return deduplicateAndSortScalars(s), nil
+ }
+
+ // Elements are maps - if one of the keys of the map is a map or a
+ // list, we may need to recurse into it.
+ newS := []interface{}{}
+ for _, elem := range s {
+ if recurse {
+ typedElem := elem.(map[string]interface{})
+ newElem, err := sortMergeListsByNameMap(typedElem, schema)
+ if err != nil {
+ return nil, err
+ }
+
+ newS = append(newS, newElem)
+ } else {
+ newS = append(newS, elem)
+ }
+ }
+
+ // Sort the maps.
+ newS = sortMapsBasedOnField(newS, mergeKey)
+ return newS, nil
+}
+
+func sortMapsBasedOnField(m []interface{}, fieldName string) []interface{} {
+ mapM := mapSliceFromSlice(m)
+ ss := SortableSliceOfMaps{mapM, fieldName}
+ sort.Sort(ss)
+ newS := sliceFromMapSlice(ss.s)
+ return newS
+}
+
+func mapSliceFromSlice(m []interface{}) []map[string]interface{} {
+ newM := []map[string]interface{}{}
+ for _, v := range m {
+ vt := v.(map[string]interface{})
+ newM = append(newM, vt)
+ }
+
+ return newM
+}
+
+func sliceFromMapSlice(s []map[string]interface{}) []interface{} {
+ newS := []interface{}{}
+ for _, v := range s {
+ newS = append(newS, v)
+ }
+
+ return newS
+}
+
+type SortableSliceOfMaps struct {
+ s []map[string]interface{}
+ k string // key to sort on
+}
+
+func (ss SortableSliceOfMaps) Len() int {
+ return len(ss.s)
+}
+
+func (ss SortableSliceOfMaps) Less(i, j int) bool {
+ iStr := fmt.Sprintf("%v", ss.s[i][ss.k])
+ jStr := fmt.Sprintf("%v", ss.s[j][ss.k])
+ return sort.StringsAreSorted([]string{iStr, jStr})
+}
+
+func (ss SortableSliceOfMaps) Swap(i, j int) {
+ tmp := ss.s[i]
+ ss.s[i] = ss.s[j]
+ ss.s[j] = tmp
+}
+
+func deduplicateAndSortScalars(s []interface{}) []interface{} {
+ s = deduplicateScalars(s)
+ return sortScalars(s)
+}
+
+func sortScalars(s []interface{}) []interface{} {
+ ss := SortableSliceOfScalars{s}
+ sort.Sort(ss)
+ return ss.s
+}
+
+func deduplicateScalars(s []interface{}) []interface{} {
+ // Clever algorithm to deduplicate.
+ length := len(s) - 1
+ for i := 0; i < length; i++ {
+ for j := i + 1; j <= length; j++ {
+ if s[i] == s[j] {
+ s[j] = s[length]
+ s = s[0:length]
+ length--
+ j--
+ }
+ }
+ }
+
+ return s
+}
+
+type SortableSliceOfScalars struct {
+ s []interface{}
+}
+
+func (ss SortableSliceOfScalars) Len() int {
+ return len(ss.s)
+}
+
+func (ss SortableSliceOfScalars) Less(i, j int) bool {
+ iStr := fmt.Sprintf("%v", ss.s[i])
+ jStr := fmt.Sprintf("%v", ss.s[j])
+ return sort.StringsAreSorted([]string{iStr, jStr})
+}
+
+func (ss SortableSliceOfScalars) Swap(i, j int) {
+ tmp := ss.s[i]
+ ss.s[i] = ss.s[j]
+ ss.s[j] = tmp
+}
+
+// Returns the type of the elements of N slice(s). If the type is different,
+// another slice or undefined, returns an error.
+func sliceElementType(slices ...[]interface{}) (reflect.Type, error) {
+ var prevType reflect.Type
+ for _, s := range slices {
+ // Go through elements of all given slices and make sure they are all the same type.
+ for _, v := range s {
+ currentType := reflect.TypeOf(v)
+ if prevType == nil {
+ prevType = currentType
+ // We don't support lists of lists yet.
+ if prevType.Kind() == reflect.Slice {
+ return nil, mergepatch.ErrNoListOfLists
+ }
+ } else {
+ if prevType != currentType {
+ return nil, fmt.Errorf("list element types are not identical: %v", fmt.Sprint(slices))
+ }
+ prevType = currentType
+ }
+ }
+ }
+
+ if prevType == nil {
+ return nil, fmt.Errorf("no elements in any of the given slices")
+ }
+
+ return prevType, nil
+}
+
+// MergingMapsHaveConflicts returns true if the left and right JSON interface
+// objects overlap with different values in any key. All keys are required to be
+// strings. Since patches of the same Type have congruent keys, this is valid
+// for multiple patch types. This method supports strategic merge patch semantics.
+func MergingMapsHaveConflicts(left, right map[string]interface{}, schema LookupPatchMeta) (bool, error) {
+ return mergingMapFieldsHaveConflicts(left, right, schema, "", "")
+}
+
+func mergingMapFieldsHaveConflicts(
+ left, right interface{},
+ schema LookupPatchMeta,
+ fieldPatchStrategy, fieldPatchMergeKey string,
+) (bool, error) {
+ switch leftType := left.(type) {
+ case map[string]interface{}:
+ rightType, ok := right.(map[string]interface{})
+ if !ok {
+ return true, nil
+ }
+ leftMarker, okLeft := leftType[directiveMarker]
+ rightMarker, okRight := rightType[directiveMarker]
+ // if one or the other has a directive marker,
+ // then we need to consider that before looking at the individual keys,
+ // since a directive operates on the whole map.
+ if okLeft || okRight {
+ // if one has a directive marker and the other doesn't,
+ // then we have a conflict, since one is deleting or replacing the whole map,
+ // and the other is doing things to individual keys.
+ if okLeft != okRight {
+ return true, nil
+ }
+ // if they both have markers, but they are not the same directive,
+ // then we have a conflict because they're doing different things to the map.
+ if leftMarker != rightMarker {
+ return true, nil
+ }
+ }
+ if fieldPatchStrategy == replaceDirective {
+ return false, nil
+ }
+ // Check the individual keys.
+ return mapsHaveConflicts(leftType, rightType, schema)
+
+ case []interface{}:
+ rightType, ok := right.([]interface{})
+ if !ok {
+ return true, nil
+ }
+ return slicesHaveConflicts(leftType, rightType, schema, fieldPatchStrategy, fieldPatchMergeKey)
+ case string, float64, bool, int64, nil:
+ return !reflect.DeepEqual(left, right), nil
+ default:
+ return true, fmt.Errorf("unknown type: %v", reflect.TypeOf(left))
+ }
+}
+
+func mapsHaveConflicts(typedLeft, typedRight map[string]interface{}, schema LookupPatchMeta) (bool, error) {
+ for key, leftValue := range typedLeft {
+ if key != directiveMarker && key != retainKeysDirective {
+ if rightValue, ok := typedRight[key]; ok {
+ var subschema LookupPatchMeta
+ var patchMeta PatchMeta
+ var patchStrategy string
+ var err error
+ switch leftValue.(type) {
+ case []interface{}:
+ subschema, patchMeta, err = schema.LookupPatchMetadataForSlice(key)
+ if err != nil {
+ return true, err
+ }
+ _, patchStrategy, err = extractRetainKeysPatchStrategy(patchMeta.patchStrategies)
+ if err != nil {
+ return true, err
+ }
+ case map[string]interface{}:
+ subschema, patchMeta, err = schema.LookupPatchMetadataForStruct(key)
+ if err != nil {
+ return true, err
+ }
+ _, patchStrategy, err = extractRetainKeysPatchStrategy(patchMeta.patchStrategies)
+ if err != nil {
+ return true, err
+ }
+ }
+
+ if hasConflicts, err := mergingMapFieldsHaveConflicts(leftValue, rightValue,
+ subschema, patchStrategy, patchMeta.GetPatchMergeKey()); hasConflicts {
+ return true, err
+ }
+ }
+ }
+ }
+
+ return false, nil
+}
+
+func slicesHaveConflicts(
+ typedLeft, typedRight []interface{},
+ schema LookupPatchMeta,
+ fieldPatchStrategy, fieldPatchMergeKey string,
+) (bool, error) {
+ elementType, err := sliceElementType(typedLeft, typedRight)
+ if err != nil {
+ return true, err
+ }
+
+ if fieldPatchStrategy == mergeDirective {
+ // Merging lists of scalars have no conflicts by definition
+ // So we only need to check further if the elements are maps
+ if elementType.Kind() != reflect.Map {
+ return false, nil
+ }
+
+ // Build a map for each slice and then compare the two maps
+ leftMap, err := sliceOfMapsToMapOfMaps(typedLeft, fieldPatchMergeKey)
+ if err != nil {
+ return true, err
+ }
+
+ rightMap, err := sliceOfMapsToMapOfMaps(typedRight, fieldPatchMergeKey)
+ if err != nil {
+ return true, err
+ }
+
+ return mapsOfMapsHaveConflicts(leftMap, rightMap, schema)
+ }
+
+ // Either we don't have type information, or these are non-merging lists
+ if len(typedLeft) != len(typedRight) {
+ return true, nil
+ }
+
+ // Sort scalar slices to prevent ordering issues
+ // We have no way to sort non-merging lists of maps
+ if elementType.Kind() != reflect.Map {
+ typedLeft = deduplicateAndSortScalars(typedLeft)
+ typedRight = deduplicateAndSortScalars(typedRight)
+ }
+
+ // Compare the slices element by element in order
+ // This test will fail if the slices are not sorted
+ for i := range typedLeft {
+ if hasConflicts, err := mergingMapFieldsHaveConflicts(typedLeft[i], typedRight[i], schema, "", ""); hasConflicts {
+ return true, err
+ }
+ }
+
+ return false, nil
+}
+
+func sliceOfMapsToMapOfMaps(slice []interface{}, mergeKey string) (map[string]interface{}, error) {
+ result := make(map[string]interface{}, len(slice))
+ for _, value := range slice {
+ typedValue, ok := value.(map[string]interface{})
+ if !ok {
+ return nil, fmt.Errorf("invalid element type in merging list:%v", slice)
+ }
+
+ mergeValue, ok := typedValue[mergeKey]
+ if !ok {
+ return nil, fmt.Errorf("cannot find merge key `%s` in merging list element:%v", mergeKey, typedValue)
+ }
+
+ result[fmt.Sprintf("%s", mergeValue)] = typedValue
+ }
+
+ return result, nil
+}
+
+func mapsOfMapsHaveConflicts(typedLeft, typedRight map[string]interface{}, schema LookupPatchMeta) (bool, error) {
+ for key, leftValue := range typedLeft {
+ if rightValue, ok := typedRight[key]; ok {
+ if hasConflicts, err := mergingMapFieldsHaveConflicts(leftValue, rightValue, schema, "", ""); hasConflicts {
+ return true, err
+ }
+ }
+ }
+
+ return false, nil
+}
+
+// CreateThreeWayMergePatch reconciles a modified configuration with an original configuration,
+// while preserving any changes or deletions made to the original configuration in the interim,
+// and not overridden by the current configuration. All three documents must be passed to the
+// method as json encoded content. It will return a strategic merge patch, or an error if any
+// of the documents is invalid, or if there are any preconditions that fail against the modified
+// configuration, or, if overwrite is false and there are conflicts between the modified and current
+// configurations. Conflicts are defined as keys changed differently from original to modified
+// than from original to current. In other words, a conflict occurs if modified changes any key
+// in a way that is different from how it is changed in current (e.g., deleting it, changing its
+// value). We also propagate values fields that do not exist in original but are explicitly
+// defined in modified.
+func CreateThreeWayMergePatch(original, modified, current []byte, schema LookupPatchMeta, overwrite bool, fns ...mergepatch.PreconditionFunc) ([]byte, error) {
+ originalMap := map[string]interface{}{}
+ if len(original) > 0 {
+ if err := json.Unmarshal(original, &originalMap); err != nil {
+ return nil, mergepatch.ErrBadJSONDoc
+ }
+ }
+
+ modifiedMap := map[string]interface{}{}
+ if len(modified) > 0 {
+ if err := json.Unmarshal(modified, &modifiedMap); err != nil {
+ return nil, mergepatch.ErrBadJSONDoc
+ }
+ }
+
+ currentMap := map[string]interface{}{}
+ if len(current) > 0 {
+ if err := json.Unmarshal(current, ¤tMap); err != nil {
+ return nil, mergepatch.ErrBadJSONDoc
+ }
+ }
+
+ // The patch is the difference from current to modified without deletions, plus deletions
+ // from original to modified. To find it, we compute deletions, which are the deletions from
+ // original to modified, and delta, which is the difference from current to modified without
+ // deletions, and then apply delta to deletions as a patch, which should be strictly additive.
+ deltaMapDiffOptions := DiffOptions{
+ IgnoreDeletions: true,
+ SetElementOrder: true,
+ }
+ deltaMap, err := diffMaps(currentMap, modifiedMap, schema, deltaMapDiffOptions)
+ if err != nil {
+ return nil, err
+ }
+ deletionsMapDiffOptions := DiffOptions{
+ SetElementOrder: true,
+ IgnoreChangesAndAdditions: true,
+ }
+ deletionsMap, err := diffMaps(originalMap, modifiedMap, schema, deletionsMapDiffOptions)
+ if err != nil {
+ return nil, err
+ }
+
+ mergeOptions := MergeOptions{}
+ patchMap, err := mergeMap(deletionsMap, deltaMap, schema, mergeOptions)
+ if err != nil {
+ return nil, err
+ }
+
+ // Apply the preconditions to the patch, and return an error if any of them fail.
+ for _, fn := range fns {
+ if !fn(patchMap) {
+ return nil, mergepatch.NewErrPreconditionFailed(patchMap)
+ }
+ }
+
+ // If overwrite is false, and the patch contains any keys that were changed differently,
+ // then return a conflict error.
+ if !overwrite {
+ changeMapDiffOptions := DiffOptions{}
+ changedMap, err := diffMaps(originalMap, currentMap, schema, changeMapDiffOptions)
+ if err != nil {
+ return nil, err
+ }
+
+ hasConflicts, err := MergingMapsHaveConflicts(patchMap, changedMap, schema)
+ if err != nil {
+ return nil, err
+ }
+
+ if hasConflicts {
+ return nil, mergepatch.NewErrConflict(mergepatch.ToYAMLOrError(patchMap), mergepatch.ToYAMLOrError(changedMap))
+ }
+ }
+
+ return json.Marshal(patchMap)
+}
+
+func ItemAddedToModifiedSlice(original, modified string) bool { return original > modified }
+
+func ItemRemovedFromModifiedSlice(original, modified string) bool { return original < modified }
+
+func ItemMatchesOriginalAndModifiedSlice(original, modified string) bool { return original == modified }
+
+func CreateDeleteDirective(mergeKey string, mergeKeyValue interface{}) map[string]interface{} {
+ return map[string]interface{}{mergeKey: mergeKeyValue, directiveMarker: deleteDirective}
+}
+
+func mapTypeAssertion(original, patch interface{}) (map[string]interface{}, map[string]interface{}, error) {
+ typedOriginal, ok := original.(map[string]interface{})
+ if !ok {
+ return nil, nil, mergepatch.ErrBadArgType(typedOriginal, original)
+ }
+ typedPatch, ok := patch.(map[string]interface{})
+ if !ok {
+ return nil, nil, mergepatch.ErrBadArgType(typedPatch, patch)
+ }
+ return typedOriginal, typedPatch, nil
+}
+
+func sliceTypeAssertion(original, patch interface{}) ([]interface{}, []interface{}, error) {
+ typedOriginal, ok := original.([]interface{})
+ if !ok {
+ return nil, nil, mergepatch.ErrBadArgType(typedOriginal, original)
+ }
+ typedPatch, ok := patch.([]interface{})
+ if !ok {
+ return nil, nil, mergepatch.ErrBadArgType(typedPatch, patch)
+ }
+ return typedOriginal, typedPatch, nil
+}
+
+// extractRetainKeysPatchStrategy process patch strategy, which is a string may contains multiple
+// patch strategies separated by ",". It returns a boolean var indicating if it has
+// retainKeys strategies and a string for the other strategy.
+func extractRetainKeysPatchStrategy(strategies []string) (bool, string, error) {
+ switch len(strategies) {
+ case 0:
+ return false, "", nil
+ case 1:
+ singleStrategy := strategies[0]
+ switch singleStrategy {
+ case retainKeysStrategy:
+ return true, "", nil
+ default:
+ return false, singleStrategy, nil
+ }
+ case 2:
+ switch {
+ case strategies[0] == retainKeysStrategy:
+ return true, strategies[1], nil
+ case strategies[1] == retainKeysStrategy:
+ return true, strategies[0], nil
+ default:
+ return false, "", fmt.Errorf("unexpected patch strategy: %v", strategies)
+ }
+ default:
+ return false, "", fmt.Errorf("unexpected patch strategy: %v", strategies)
+ }
+}
+
+// hasAdditionalNewField returns if original map has additional key with non-nil value than modified.
+func hasAdditionalNewField(original, modified map[string]interface{}) bool {
+ for k, v := range original {
+ if v == nil {
+ continue
+ }
+ if _, found := modified[k]; !found {
+ return true
+ }
+ }
+ return false
+}
diff --git a/vendor/k8s.io/apimachinery/pkg/util/strategicpatch/types.go b/vendor/k8s.io/apimachinery/pkg/util/strategicpatch/types.go
new file mode 100644
index 000000000..f84d65aac
--- /dev/null
+++ b/vendor/k8s.io/apimachinery/pkg/util/strategicpatch/types.go
@@ -0,0 +1,193 @@
+/*
+Copyright 2017 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 strategicpatch
+
+import (
+ "errors"
+ "strings"
+
+ "k8s.io/apimachinery/pkg/util/mergepatch"
+ openapi "k8s.io/kube-openapi/pkg/util/proto"
+)
+
+const (
+ patchStrategyOpenapiextensionKey = "x-kubernetes-patch-strategy"
+ patchMergeKeyOpenapiextensionKey = "x-kubernetes-patch-merge-key"
+)
+
+type LookupPatchItem interface {
+ openapi.SchemaVisitor
+
+ Error() error
+ Path() *openapi.Path
+}
+
+type kindItem struct {
+ key string
+ path *openapi.Path
+ err error
+ patchmeta PatchMeta
+ subschema openapi.Schema
+ hasVisitKind bool
+}
+
+func NewKindItem(key string, path *openapi.Path) *kindItem {
+ return &kindItem{
+ key: key,
+ path: path,
+ }
+}
+
+var _ LookupPatchItem = &kindItem{}
+
+func (item *kindItem) Error() error {
+ return item.err
+}
+
+func (item *kindItem) Path() *openapi.Path {
+ return item.path
+}
+
+func (item *kindItem) VisitPrimitive(schema *openapi.Primitive) {
+ item.err = errors.New("expected kind, but got primitive")
+}
+
+func (item *kindItem) VisitArray(schema *openapi.Array) {
+ item.err = errors.New("expected kind, but got slice")
+}
+
+func (item *kindItem) VisitMap(schema *openapi.Map) {
+ item.err = errors.New("expected kind, but got map")
+}
+
+func (item *kindItem) VisitReference(schema openapi.Reference) {
+ if !item.hasVisitKind {
+ schema.SubSchema().Accept(item)
+ }
+}
+
+func (item *kindItem) VisitKind(schema *openapi.Kind) {
+ subschema, ok := schema.Fields[item.key]
+ if !ok {
+ item.err = FieldNotFoundError{Path: schema.GetPath().String(), Field: item.key}
+ return
+ }
+
+ mergeKey, patchStrategies, err := parsePatchMetadata(subschema.GetExtensions())
+ if err != nil {
+ item.err = err
+ return
+ }
+ item.patchmeta = PatchMeta{
+ patchStrategies: patchStrategies,
+ patchMergeKey: mergeKey,
+ }
+ item.subschema = subschema
+}
+
+type sliceItem struct {
+ key string
+ path *openapi.Path
+ err error
+ patchmeta PatchMeta
+ subschema openapi.Schema
+ hasVisitKind bool
+}
+
+func NewSliceItem(key string, path *openapi.Path) *sliceItem {
+ return &sliceItem{
+ key: key,
+ path: path,
+ }
+}
+
+var _ LookupPatchItem = &sliceItem{}
+
+func (item *sliceItem) Error() error {
+ return item.err
+}
+
+func (item *sliceItem) Path() *openapi.Path {
+ return item.path
+}
+
+func (item *sliceItem) VisitPrimitive(schema *openapi.Primitive) {
+ item.err = errors.New("expected slice, but got primitive")
+}
+
+func (item *sliceItem) VisitArray(schema *openapi.Array) {
+ if !item.hasVisitKind {
+ item.err = errors.New("expected visit kind first, then visit array")
+ }
+ subschema := schema.SubType
+ item.subschema = subschema
+}
+
+func (item *sliceItem) VisitMap(schema *openapi.Map) {
+ item.err = errors.New("expected slice, but got map")
+}
+
+func (item *sliceItem) VisitReference(schema openapi.Reference) {
+ if !item.hasVisitKind {
+ schema.SubSchema().Accept(item)
+ } else {
+ item.subschema = schema.SubSchema()
+ }
+}
+
+func (item *sliceItem) VisitKind(schema *openapi.Kind) {
+ subschema, ok := schema.Fields[item.key]
+ if !ok {
+ item.err = FieldNotFoundError{Path: schema.GetPath().String(), Field: item.key}
+ return
+ }
+
+ mergeKey, patchStrategies, err := parsePatchMetadata(subschema.GetExtensions())
+ if err != nil {
+ item.err = err
+ return
+ }
+ item.patchmeta = PatchMeta{
+ patchStrategies: patchStrategies,
+ patchMergeKey: mergeKey,
+ }
+ item.hasVisitKind = true
+ subschema.Accept(item)
+}
+
+func parsePatchMetadata(extensions map[string]interface{}) (string, []string, error) {
+ ps, foundPS := extensions[patchStrategyOpenapiextensionKey]
+ var patchStrategies []string
+ var mergeKey, patchStrategy string
+ var ok bool
+ if foundPS {
+ patchStrategy, ok = ps.(string)
+ if ok {
+ patchStrategies = strings.Split(patchStrategy, ",")
+ } else {
+ return "", nil, mergepatch.ErrBadArgType(patchStrategy, ps)
+ }
+ }
+ mk, foundMK := extensions[patchMergeKeyOpenapiextensionKey]
+ if foundMK {
+ mergeKey, ok = mk.(string)
+ if !ok {
+ return "", nil, mergepatch.ErrBadArgType(mergeKey, mk)
+ }
+ }
+ return mergeKey, patchStrategies, nil
+}
diff --git a/vendor/k8s.io/apimachinery/third_party/forked/golang/json/OWNERS b/vendor/k8s.io/apimachinery/third_party/forked/golang/json/OWNERS
new file mode 100644
index 000000000..3f72c69ba
--- /dev/null
+++ b/vendor/k8s.io/apimachinery/third_party/forked/golang/json/OWNERS
@@ -0,0 +1,7 @@
+# See the OWNERS docs at https://go.k8s.io/owners
+
+approvers:
+- pwittrock
+reviewers:
+- mengqiy
+- apelisse
diff --git a/vendor/k8s.io/apimachinery/third_party/forked/golang/json/fields.go b/vendor/k8s.io/apimachinery/third_party/forked/golang/json/fields.go
new file mode 100644
index 000000000..8205a4dd1
--- /dev/null
+++ b/vendor/k8s.io/apimachinery/third_party/forked/golang/json/fields.go
@@ -0,0 +1,513 @@
+// 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 json is forked from the Go standard library to enable us to find the
+// field of a struct that a given JSON key maps to.
+package json
+
+import (
+ "bytes"
+ "fmt"
+ "reflect"
+ "sort"
+ "strings"
+ "sync"
+ "unicode"
+ "unicode/utf8"
+)
+
+const (
+ patchStrategyTagKey = "patchStrategy"
+ patchMergeKeyTagKey = "patchMergeKey"
+)
+
+// Finds the patchStrategy and patchMergeKey struct tag fields on a given
+// struct field given the struct type and the JSON name of the field.
+// It returns field type, a slice of patch strategies, merge key and error.
+// TODO: fix the returned errors to be introspectable.
+func LookupPatchMetadataForStruct(t reflect.Type, jsonField string) (
+ elemType reflect.Type, patchStrategies []string, patchMergeKey string, e error) {
+ if t.Kind() == reflect.Ptr {
+ t = t.Elem()
+ }
+
+ if t.Kind() != reflect.Struct {
+ e = fmt.Errorf("merging an object in json but data type is not struct, instead is: %s",
+ t.Kind().String())
+ return
+ }
+ jf := []byte(jsonField)
+ // Find the field that the JSON library would use.
+ var f *field
+ fields := cachedTypeFields(t)
+ for i := range fields {
+ ff := &fields[i]
+ if bytes.Equal(ff.nameBytes, jf) {
+ f = ff
+ break
+ }
+ // Do case-insensitive comparison.
+ if f == nil && ff.equalFold(ff.nameBytes, jf) {
+ f = ff
+ }
+ }
+ if f != nil {
+ // Find the reflect.Value of the most preferential struct field.
+ tjf := t.Field(f.index[0])
+ // we must navigate down all the anonymously included structs in the chain
+ for i := 1; i < len(f.index); i++ {
+ tjf = tjf.Type.Field(f.index[i])
+ }
+ patchStrategy := tjf.Tag.Get(patchStrategyTagKey)
+ patchMergeKey = tjf.Tag.Get(patchMergeKeyTagKey)
+ patchStrategies = strings.Split(patchStrategy, ",")
+ elemType = tjf.Type
+ return
+ }
+ e = fmt.Errorf("unable to find api field in struct %s for the json field %q", t.Name(), jsonField)
+ return
+}
+
+// A field represents a single field found in a struct.
+type field struct {
+ name string
+ nameBytes []byte // []byte(name)
+ equalFold func(s, t []byte) bool // bytes.EqualFold or equivalent
+
+ tag bool
+ // index is the sequence of indexes from the containing type fields to this field.
+ // it is a slice because anonymous structs will need multiple navigation steps to correctly
+ // resolve the proper fields
+ index []int
+ typ reflect.Type
+ omitEmpty bool
+ quoted bool
+}
+
+func (f field) String() string {
+ return fmt.Sprintf("{name: %s, type: %v, tag: %v, index: %v, omitEmpty: %v, quoted: %v}", f.name, f.typ, f.tag, f.index, f.omitEmpty, f.quoted)
+}
+
+func fillField(f field) field {
+ f.nameBytes = []byte(f.name)
+ f.equalFold = foldFunc(f.nameBytes)
+ return f
+}
+
+// byName sorts field by name, breaking ties with depth,
+// then breaking ties with "name came from json tag", then
+// breaking ties with index sequence.
+type byName []field
+
+func (x byName) Len() int { return len(x) }
+
+func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+
+func (x byName) Less(i, j int) bool {
+ if x[i].name != x[j].name {
+ return x[i].name < x[j].name
+ }
+ if len(x[i].index) != len(x[j].index) {
+ return len(x[i].index) < len(x[j].index)
+ }
+ if x[i].tag != x[j].tag {
+ return x[i].tag
+ }
+ return byIndex(x).Less(i, j)
+}
+
+// byIndex sorts field by index sequence.
+type byIndex []field
+
+func (x byIndex) Len() int { return len(x) }
+
+func (x byIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+
+func (x byIndex) Less(i, j int) bool {
+ for k, xik := range x[i].index {
+ if k >= len(x[j].index) {
+ return false
+ }
+ if xik != x[j].index[k] {
+ return xik < x[j].index[k]
+ }
+ }
+ return len(x[i].index) < len(x[j].index)
+}
+
+// typeFields returns a list of fields that JSON should recognize for the given type.
+// The algorithm is breadth-first search over the set of structs to include - the top struct
+// and then any reachable anonymous structs.
+func typeFields(t reflect.Type) []field {
+ // Anonymous fields to explore at the current level and the next.
+ current := []field{}
+ next := []field{{typ: t}}
+
+ // Count of queued names for current level and the next.
+ count := map[reflect.Type]int{}
+ nextCount := map[reflect.Type]int{}
+
+ // Types already visited at an earlier level.
+ visited := map[reflect.Type]bool{}
+
+ // Fields found.
+ var fields []field
+
+ for len(next) > 0 {
+ current, next = next, current[:0]
+ count, nextCount = nextCount, map[reflect.Type]int{}
+
+ for _, f := range current {
+ if visited[f.typ] {
+ continue
+ }
+ visited[f.typ] = true
+
+ // Scan f.typ for fields to include.
+ for i := 0; i < f.typ.NumField(); i++ {
+ sf := f.typ.Field(i)
+ if sf.PkgPath != "" { // unexported
+ continue
+ }
+ tag := sf.Tag.Get("json")
+ if tag == "-" {
+ continue
+ }
+ name, opts := parseTag(tag)
+ if !isValidTag(name) {
+ name = ""
+ }
+ index := make([]int, len(f.index)+1)
+ copy(index, f.index)
+ index[len(f.index)] = i
+
+ ft := sf.Type
+ if ft.Name() == "" && ft.Kind() == reflect.Ptr {
+ // Follow pointer.
+ ft = ft.Elem()
+ }
+
+ // Record found field and index sequence.
+ if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
+ tagged := name != ""
+ if name == "" {
+ name = sf.Name
+ }
+ fields = append(fields, fillField(field{
+ name: name,
+ tag: tagged,
+ index: index,
+ typ: ft,
+ omitEmpty: opts.Contains("omitempty"),
+ quoted: opts.Contains("string"),
+ }))
+ if count[f.typ] > 1 {
+ // If there were multiple instances, add a second,
+ // so that the annihilation code will see a duplicate.
+ // It only cares about the distinction between 1 or 2,
+ // so don't bother generating any more copies.
+ fields = append(fields, fields[len(fields)-1])
+ }
+ continue
+ }
+
+ // Record new anonymous struct to explore in next round.
+ nextCount[ft]++
+ if nextCount[ft] == 1 {
+ next = append(next, fillField(field{name: ft.Name(), index: index, typ: ft}))
+ }
+ }
+ }
+ }
+
+ sort.Sort(byName(fields))
+
+ // Delete all fields that are hidden by the Go rules for embedded fields,
+ // except that fields with JSON tags are promoted.
+
+ // The fields are sorted in primary order of name, secondary order
+ // of field index length. Loop over names; for each name, delete
+ // hidden fields by choosing the one dominant field that survives.
+ out := fields[:0]
+ for advance, i := 0, 0; i < len(fields); i += advance {
+ // One iteration per name.
+ // Find the sequence of fields with the name of this first field.
+ fi := fields[i]
+ name := fi.name
+ for advance = 1; i+advance < len(fields); advance++ {
+ fj := fields[i+advance]
+ if fj.name != name {
+ break
+ }
+ }
+ if advance == 1 { // Only one field with this name
+ out = append(out, fi)
+ continue
+ }
+ dominant, ok := dominantField(fields[i : i+advance])
+ if ok {
+ out = append(out, dominant)
+ }
+ }
+
+ fields = out
+ sort.Sort(byIndex(fields))
+
+ return fields
+}
+
+// dominantField looks through the fields, all of which are known to
+// have the same name, to find the single field that dominates the
+// others using Go's embedding rules, modified by the presence of
+// JSON tags. If there are multiple top-level fields, the boolean
+// will be false: This condition is an error in Go and we skip all
+// the fields.
+func dominantField(fields []field) (field, bool) {
+ // The fields are sorted in increasing index-length order. The winner
+ // must therefore be one with the shortest index length. Drop all
+ // longer entries, which is easy: just truncate the slice.
+ length := len(fields[0].index)
+ tagged := -1 // Index of first tagged field.
+ for i, f := range fields {
+ if len(f.index) > length {
+ fields = fields[:i]
+ break
+ }
+ if f.tag {
+ if tagged >= 0 {
+ // Multiple tagged fields at the same level: conflict.
+ // Return no field.
+ return field{}, false
+ }
+ tagged = i
+ }
+ }
+ if tagged >= 0 {
+ return fields[tagged], true
+ }
+ // All remaining fields have the same length. If there's more than one,
+ // we have a conflict (two fields named "X" at the same level) and we
+ // return no field.
+ if len(fields) > 1 {
+ return field{}, false
+ }
+ return fields[0], true
+}
+
+var fieldCache struct {
+ sync.RWMutex
+ m map[reflect.Type][]field
+}
+
+// cachedTypeFields is like typeFields but uses a cache to avoid repeated work.
+func cachedTypeFields(t reflect.Type) []field {
+ fieldCache.RLock()
+ f := fieldCache.m[t]
+ fieldCache.RUnlock()
+ if f != nil {
+ return f
+ }
+
+ // Compute fields without lock.
+ // Might duplicate effort but won't hold other computations back.
+ f = typeFields(t)
+ if f == nil {
+ f = []field{}
+ }
+
+ fieldCache.Lock()
+ if fieldCache.m == nil {
+ fieldCache.m = map[reflect.Type][]field{}
+ }
+ fieldCache.m[t] = f
+ fieldCache.Unlock()
+ return f
+}
+
+func isValidTag(s string) bool {
+ if s == "" {
+ return false
+ }
+ for _, c := range s {
+ switch {
+ case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~ ", c):
+ // Backslash and quote chars are reserved, but
+ // otherwise any punctuation chars are allowed
+ // in a tag name.
+ default:
+ if !unicode.IsLetter(c) && !unicode.IsDigit(c) {
+ return false
+ }
+ }
+ }
+ return true
+}
+
+const (
+ caseMask = ^byte(0x20) // Mask to ignore case in ASCII.
+ kelvin = '\u212a'
+ smallLongEss = '\u017f'
+)
+
+// foldFunc returns one of four different case folding equivalence
+// functions, from most general (and slow) to fastest:
+//
+// 1) bytes.EqualFold, if the key s contains any non-ASCII UTF-8
+// 2) equalFoldRight, if s contains special folding ASCII ('k', 'K', 's', 'S')
+// 3) asciiEqualFold, no special, but includes non-letters (including _)
+// 4) simpleLetterEqualFold, no specials, no non-letters.
+//
+// The letters S and K are special because they map to 3 runes, not just 2:
+// * S maps to s and to U+017F 'Å¿' Latin small letter long s
+// * k maps to K and to U+212A 'K' Kelvin sign
+// See http://play.golang.org/p/tTxjOc0OGo
+//
+// The returned function is specialized for matching against s and
+// should only be given s. It's not curried for performance reasons.
+func foldFunc(s []byte) func(s, t []byte) bool {
+ nonLetter := false
+ special := false // special letter
+ for _, b := range s {
+ if b >= utf8.RuneSelf {
+ return bytes.EqualFold
+ }
+ upper := b & caseMask
+ if upper < 'A' || upper > 'Z' {
+ nonLetter = true
+ } else if upper == 'K' || upper == 'S' {
+ // See above for why these letters are special.
+ special = true
+ }
+ }
+ if special {
+ return equalFoldRight
+ }
+ if nonLetter {
+ return asciiEqualFold
+ }
+ return simpleLetterEqualFold
+}
+
+// equalFoldRight is a specialization of bytes.EqualFold when s is
+// known to be all ASCII (including punctuation), but contains an 's',
+// 'S', 'k', or 'K', requiring a Unicode fold on the bytes in t.
+// See comments on foldFunc.
+func equalFoldRight(s, t []byte) bool {
+ for _, sb := range s {
+ if len(t) == 0 {
+ return false
+ }
+ tb := t[0]
+ if tb < utf8.RuneSelf {
+ if sb != tb {
+ sbUpper := sb & caseMask
+ if 'A' <= sbUpper && sbUpper <= 'Z' {
+ if sbUpper != tb&caseMask {
+ return false
+ }
+ } else {
+ return false
+ }
+ }
+ t = t[1:]
+ continue
+ }
+ // sb is ASCII and t is not. t must be either kelvin
+ // sign or long s; sb must be s, S, k, or K.
+ tr, size := utf8.DecodeRune(t)
+ switch sb {
+ case 's', 'S':
+ if tr != smallLongEss {
+ return false
+ }
+ case 'k', 'K':
+ if tr != kelvin {
+ return false
+ }
+ default:
+ return false
+ }
+ t = t[size:]
+
+ }
+ if len(t) > 0 {
+ return false
+ }
+ return true
+}
+
+// asciiEqualFold is a specialization of bytes.EqualFold for use when
+// s is all ASCII (but may contain non-letters) and contains no
+// special-folding letters.
+// See comments on foldFunc.
+func asciiEqualFold(s, t []byte) bool {
+ if len(s) != len(t) {
+ return false
+ }
+ for i, sb := range s {
+ tb := t[i]
+ if sb == tb {
+ continue
+ }
+ if ('a' <= sb && sb <= 'z') || ('A' <= sb && sb <= 'Z') {
+ if sb&caseMask != tb&caseMask {
+ return false
+ }
+ } else {
+ return false
+ }
+ }
+ return true
+}
+
+// simpleLetterEqualFold is a specialization of bytes.EqualFold for
+// use when s is all ASCII letters (no underscores, etc) and also
+// doesn't contain 'k', 'K', 's', or 'S'.
+// See comments on foldFunc.
+func simpleLetterEqualFold(s, t []byte) bool {
+ if len(s) != len(t) {
+ return false
+ }
+ for i, b := range s {
+ if b&caseMask != t[i]&caseMask {
+ return false
+ }
+ }
+ return true
+}
+
+// tagOptions is the string following a comma in a struct field's "json"
+// tag, or the empty string. It does not include the leading comma.
+type tagOptions string
+
+// parseTag splits a struct field's json tag into its name and
+// comma-separated options.
+func parseTag(tag string) (string, tagOptions) {
+ if idx := strings.Index(tag, ","); idx != -1 {
+ return tag[:idx], tagOptions(tag[idx+1:])
+ }
+ return tag, tagOptions("")
+}
+
+// Contains reports whether a comma-separated list of options
+// contains a particular substr flag. substr must be surrounded by a
+// string boundary or commas.
+func (o tagOptions) Contains(optionName string) bool {
+ if len(o) == 0 {
+ return false
+ }
+ s := string(o)
+ for s != "" {
+ var next string
+ i := strings.Index(s, ",")
+ if i >= 0 {
+ s, next = s[:i], s[i+1:]
+ }
+ if s == optionName {
+ return true
+ }
+ s = next
+ }
+ return false
+}
diff --git a/vendor/k8s.io/client-go/discovery/fake/discovery.go b/vendor/k8s.io/client-go/discovery/fake/discovery.go
new file mode 100644
index 000000000..335473dd1
--- /dev/null
+++ b/vendor/k8s.io/client-go/discovery/fake/discovery.go
@@ -0,0 +1,160 @@
+/*
+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 (
+ "fmt"
+
+ "github.com/googleapis/gnostic/OpenAPIv2"
+
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/apimachinery/pkg/version"
+ kubeversion "k8s.io/client-go/pkg/version"
+ restclient "k8s.io/client-go/rest"
+ "k8s.io/client-go/testing"
+)
+
+// FakeDiscovery implements discovery.DiscoveryInterface and sometimes calls testing.Fake.Invoke with an action,
+// but doesn't respect the return value if any. There is a way to fake static values like ServerVersion by using the Faked... fields on the struct.
+type FakeDiscovery struct {
+ *testing.Fake
+ FakedServerVersion *version.Info
+}
+
+// ServerResourcesForGroupVersion returns the supported resources for a group
+// and version.
+func (c *FakeDiscovery) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) {
+ action := testing.ActionImpl{
+ Verb: "get",
+ Resource: schema.GroupVersionResource{Resource: "resource"},
+ }
+ c.Invokes(action, nil)
+ for _, resourceList := range c.Resources {
+ if resourceList.GroupVersion == groupVersion {
+ return resourceList, nil
+ }
+ }
+ return nil, fmt.Errorf("GroupVersion %q not found", groupVersion)
+}
+
+// ServerResources returns the supported resources for all groups and versions.
+// Deprecated: use ServerGroupsAndResources instead.
+func (c *FakeDiscovery) ServerResources() ([]*metav1.APIResourceList, error) {
+ _, rs, err := c.ServerGroupsAndResources()
+ return rs, err
+}
+
+// ServerGroupsAndResources returns the supported groups and resources for all groups and versions.
+func (c *FakeDiscovery) ServerGroupsAndResources() ([]*metav1.APIGroup, []*metav1.APIResourceList, error) {
+ sgs, err := c.ServerGroups()
+ if err != nil {
+ return nil, nil, err
+ }
+ resultGroups := []*metav1.APIGroup{}
+ for i := range sgs.Groups {
+ resultGroups = append(resultGroups, &sgs.Groups[i])
+ }
+
+ action := testing.ActionImpl{
+ Verb: "get",
+ Resource: schema.GroupVersionResource{Resource: "resource"},
+ }
+ c.Invokes(action, nil)
+ return resultGroups, c.Resources, nil
+}
+
+// ServerPreferredResources returns the supported resources with the version
+// preferred by the server.
+func (c *FakeDiscovery) ServerPreferredResources() ([]*metav1.APIResourceList, error) {
+ return nil, nil
+}
+
+// ServerPreferredNamespacedResources returns the supported namespaced resources
+// with the version preferred by the server.
+func (c *FakeDiscovery) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) {
+ return nil, nil
+}
+
+// ServerGroups returns the supported groups, with information like supported
+// versions and the preferred version.
+func (c *FakeDiscovery) ServerGroups() (*metav1.APIGroupList, error) {
+ action := testing.ActionImpl{
+ Verb: "get",
+ Resource: schema.GroupVersionResource{Resource: "group"},
+ }
+ c.Invokes(action, nil)
+
+ groups := map[string]*metav1.APIGroup{}
+
+ for _, res := range c.Resources {
+ gv, err := schema.ParseGroupVersion(res.GroupVersion)
+ if err != nil {
+ return nil, err
+ }
+ group := groups[gv.Group]
+ if group == nil {
+ group = &metav1.APIGroup{
+ Name: gv.Group,
+ PreferredVersion: metav1.GroupVersionForDiscovery{
+ GroupVersion: res.GroupVersion,
+ Version: gv.Version,
+ },
+ }
+ groups[gv.Group] = group
+ }
+
+ group.Versions = append(group.Versions, metav1.GroupVersionForDiscovery{
+ GroupVersion: res.GroupVersion,
+ Version: gv.Version,
+ })
+ }
+
+ list := &metav1.APIGroupList{}
+ for _, apiGroup := range groups {
+ list.Groups = append(list.Groups, *apiGroup)
+ }
+
+ return list, nil
+
+}
+
+// ServerVersion retrieves and parses the server's version.
+func (c *FakeDiscovery) ServerVersion() (*version.Info, error) {
+ action := testing.ActionImpl{}
+ action.Verb = "get"
+ action.Resource = schema.GroupVersionResource{Resource: "version"}
+ c.Invokes(action, nil)
+
+ if c.FakedServerVersion != nil {
+ return c.FakedServerVersion, nil
+ }
+
+ versionInfo := kubeversion.Get()
+ return &versionInfo, nil
+}
+
+// OpenAPISchema retrieves and parses the swagger API schema the server supports.
+func (c *FakeDiscovery) OpenAPISchema() (*openapi_v2.Document, error) {
+ return &openapi_v2.Document{}, nil
+}
+
+// RESTClient returns a RESTClient that is used to communicate with API server
+// by this client implementation.
+func (c *FakeDiscovery) RESTClient() restclient.Interface {
+ return nil
+}
diff --git a/vendor/k8s.io/client-go/dynamic/fake/simple.go b/vendor/k8s.io/client-go/dynamic/fake/simple.go
new file mode 100644
index 000000000..819b8d9c9
--- /dev/null
+++ b/vendor/k8s.io/client-go/dynamic/fake/simple.go
@@ -0,0 +1,370 @@
+/*
+Copyright 2018 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 (
+ "strings"
+
+ "k8s.io/apimachinery/pkg/api/meta"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+ "k8s.io/apimachinery/pkg/labels"
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/apimachinery/pkg/runtime/serializer"
+ "k8s.io/apimachinery/pkg/types"
+ "k8s.io/apimachinery/pkg/watch"
+ "k8s.io/client-go/dynamic"
+ "k8s.io/client-go/testing"
+)
+
+func NewSimpleDynamicClient(scheme *runtime.Scheme, objects ...runtime.Object) *FakeDynamicClient {
+ // In order to use List with this client, you have to have the v1.List registered in your scheme. Neat thing though
+ // it does NOT have to be the *same* list
+ scheme.AddKnownTypeWithName(schema.GroupVersionKind{Group: "fake-dynamic-client-group", Version: "v1", Kind: "List"}, &unstructured.UnstructuredList{})
+
+ codecs := serializer.NewCodecFactory(scheme)
+ o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder())
+ for _, obj := range objects {
+ if err := o.Add(obj); err != nil {
+ panic(err)
+ }
+ }
+
+ cs := &FakeDynamicClient{scheme: scheme}
+ cs.AddReactor("*", "*", testing.ObjectReaction(o))
+ cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) {
+ gvr := action.GetResource()
+ ns := action.GetNamespace()
+ watch, err := o.Watch(gvr, ns)
+ if err != nil {
+ return false, nil, err
+ }
+ return true, watch, nil
+ })
+
+ return cs
+}
+
+// Clientset implements clientset.Interface. Meant to be embedded into a
+// struct to get a default implementation. This makes faking out just the method
+// you want to test easier.
+type FakeDynamicClient struct {
+ testing.Fake
+ scheme *runtime.Scheme
+}
+
+type dynamicResourceClient struct {
+ client *FakeDynamicClient
+ namespace string
+ resource schema.GroupVersionResource
+}
+
+var _ dynamic.Interface = &FakeDynamicClient{}
+
+func (c *FakeDynamicClient) Resource(resource schema.GroupVersionResource) dynamic.NamespaceableResourceInterface {
+ return &dynamicResourceClient{client: c, resource: resource}
+}
+
+func (c *dynamicResourceClient) Namespace(ns string) dynamic.ResourceInterface {
+ ret := *c
+ ret.namespace = ns
+ return &ret
+}
+
+func (c *dynamicResourceClient) Create(obj *unstructured.Unstructured, opts metav1.CreateOptions, subresources ...string) (*unstructured.Unstructured, error) {
+ var uncastRet runtime.Object
+ var err error
+ switch {
+ case len(c.namespace) == 0 && len(subresources) == 0:
+ uncastRet, err = c.client.Fake.
+ Invokes(testing.NewRootCreateAction(c.resource, obj), obj)
+
+ case len(c.namespace) == 0 && len(subresources) > 0:
+ accessor, err := meta.Accessor(obj)
+ if err != nil {
+ return nil, err
+ }
+ name := accessor.GetName()
+ uncastRet, err = c.client.Fake.
+ Invokes(testing.NewRootCreateSubresourceAction(c.resource, name, strings.Join(subresources, "/"), obj), obj)
+
+ case len(c.namespace) > 0 && len(subresources) == 0:
+ uncastRet, err = c.client.Fake.
+ Invokes(testing.NewCreateAction(c.resource, c.namespace, obj), obj)
+
+ case len(c.namespace) > 0 && len(subresources) > 0:
+ accessor, err := meta.Accessor(obj)
+ if err != nil {
+ return nil, err
+ }
+ name := accessor.GetName()
+ uncastRet, err = c.client.Fake.
+ Invokes(testing.NewCreateSubresourceAction(c.resource, name, strings.Join(subresources, "/"), c.namespace, obj), obj)
+
+ }
+
+ if err != nil {
+ return nil, err
+ }
+ if uncastRet == nil {
+ return nil, err
+ }
+
+ ret := &unstructured.Unstructured{}
+ if err := c.client.scheme.Convert(uncastRet, ret, nil); err != nil {
+ return nil, err
+ }
+ return ret, err
+}
+
+func (c *dynamicResourceClient) Update(obj *unstructured.Unstructured, opts metav1.UpdateOptions, subresources ...string) (*unstructured.Unstructured, error) {
+ var uncastRet runtime.Object
+ var err error
+ switch {
+ case len(c.namespace) == 0 && len(subresources) == 0:
+ uncastRet, err = c.client.Fake.
+ Invokes(testing.NewRootUpdateAction(c.resource, obj), obj)
+
+ case len(c.namespace) == 0 && len(subresources) > 0:
+ uncastRet, err = c.client.Fake.
+ Invokes(testing.NewRootUpdateSubresourceAction(c.resource, strings.Join(subresources, "/"), obj), obj)
+
+ case len(c.namespace) > 0 && len(subresources) == 0:
+ uncastRet, err = c.client.Fake.
+ Invokes(testing.NewUpdateAction(c.resource, c.namespace, obj), obj)
+
+ case len(c.namespace) > 0 && len(subresources) > 0:
+ uncastRet, err = c.client.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(c.resource, strings.Join(subresources, "/"), c.namespace, obj), obj)
+
+ }
+
+ if err != nil {
+ return nil, err
+ }
+ if uncastRet == nil {
+ return nil, err
+ }
+
+ ret := &unstructured.Unstructured{}
+ if err := c.client.scheme.Convert(uncastRet, ret, nil); err != nil {
+ return nil, err
+ }
+ return ret, err
+}
+
+func (c *dynamicResourceClient) UpdateStatus(obj *unstructured.Unstructured, opts metav1.UpdateOptions) (*unstructured.Unstructured, error) {
+ var uncastRet runtime.Object
+ var err error
+ switch {
+ case len(c.namespace) == 0:
+ uncastRet, err = c.client.Fake.
+ Invokes(testing.NewRootUpdateSubresourceAction(c.resource, "status", obj), obj)
+
+ case len(c.namespace) > 0:
+ uncastRet, err = c.client.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(c.resource, "status", c.namespace, obj), obj)
+
+ }
+
+ if err != nil {
+ return nil, err
+ }
+ if uncastRet == nil {
+ return nil, err
+ }
+
+ ret := &unstructured.Unstructured{}
+ if err := c.client.scheme.Convert(uncastRet, ret, nil); err != nil {
+ return nil, err
+ }
+ return ret, err
+}
+
+func (c *dynamicResourceClient) Delete(name string, opts *metav1.DeleteOptions, subresources ...string) error {
+ var err error
+ switch {
+ case len(c.namespace) == 0 && len(subresources) == 0:
+ _, err = c.client.Fake.
+ Invokes(testing.NewRootDeleteAction(c.resource, name), &metav1.Status{Status: "dynamic delete fail"})
+
+ case len(c.namespace) == 0 && len(subresources) > 0:
+ _, err = c.client.Fake.
+ Invokes(testing.NewRootDeleteSubresourceAction(c.resource, strings.Join(subresources, "/"), name), &metav1.Status{Status: "dynamic delete fail"})
+
+ case len(c.namespace) > 0 && len(subresources) == 0:
+ _, err = c.client.Fake.
+ Invokes(testing.NewDeleteAction(c.resource, c.namespace, name), &metav1.Status{Status: "dynamic delete fail"})
+
+ case len(c.namespace) > 0 && len(subresources) > 0:
+ _, err = c.client.Fake.
+ Invokes(testing.NewDeleteSubresourceAction(c.resource, strings.Join(subresources, "/"), c.namespace, name), &metav1.Status{Status: "dynamic delete fail"})
+ }
+
+ return err
+}
+
+func (c *dynamicResourceClient) DeleteCollection(opts *metav1.DeleteOptions, listOptions metav1.ListOptions) error {
+ var err error
+ switch {
+ case len(c.namespace) == 0:
+ action := testing.NewRootDeleteCollectionAction(c.resource, listOptions)
+ _, err = c.client.Fake.Invokes(action, &metav1.Status{Status: "dynamic deletecollection fail"})
+
+ case len(c.namespace) > 0:
+ action := testing.NewDeleteCollectionAction(c.resource, c.namespace, listOptions)
+ _, err = c.client.Fake.Invokes(action, &metav1.Status{Status: "dynamic deletecollection fail"})
+
+ }
+
+ return err
+}
+
+func (c *dynamicResourceClient) Get(name string, opts metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, error) {
+ var uncastRet runtime.Object
+ var err error
+ switch {
+ case len(c.namespace) == 0 && len(subresources) == 0:
+ uncastRet, err = c.client.Fake.
+ Invokes(testing.NewRootGetAction(c.resource, name), &metav1.Status{Status: "dynamic get fail"})
+
+ case len(c.namespace) == 0 && len(subresources) > 0:
+ uncastRet, err = c.client.Fake.
+ Invokes(testing.NewRootGetSubresourceAction(c.resource, strings.Join(subresources, "/"), name), &metav1.Status{Status: "dynamic get fail"})
+
+ case len(c.namespace) > 0 && len(subresources) == 0:
+ uncastRet, err = c.client.Fake.
+ Invokes(testing.NewGetAction(c.resource, c.namespace, name), &metav1.Status{Status: "dynamic get fail"})
+
+ case len(c.namespace) > 0 && len(subresources) > 0:
+ uncastRet, err = c.client.Fake.
+ Invokes(testing.NewGetSubresourceAction(c.resource, c.namespace, strings.Join(subresources, "/"), name), &metav1.Status{Status: "dynamic get fail"})
+ }
+
+ if err != nil {
+ return nil, err
+ }
+ if uncastRet == nil {
+ return nil, err
+ }
+
+ ret := &unstructured.Unstructured{}
+ if err := c.client.scheme.Convert(uncastRet, ret, nil); err != nil {
+ return nil, err
+ }
+ return ret, err
+}
+
+func (c *dynamicResourceClient) List(opts metav1.ListOptions) (*unstructured.UnstructuredList, error) {
+ var obj runtime.Object
+ var err error
+ switch {
+ case len(c.namespace) == 0:
+ obj, err = c.client.Fake.
+ Invokes(testing.NewRootListAction(c.resource, schema.GroupVersionKind{Group: "fake-dynamic-client-group", Version: "v1", Kind: "" /*List is appended by the tracker automatically*/}, opts), &metav1.Status{Status: "dynamic list fail"})
+
+ case len(c.namespace) > 0:
+ obj, err = c.client.Fake.
+ Invokes(testing.NewListAction(c.resource, schema.GroupVersionKind{Group: "fake-dynamic-client-group", Version: "v1", Kind: "" /*List is appended by the tracker automatically*/}, c.namespace, opts), &metav1.Status{Status: "dynamic list fail"})
+
+ }
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+
+ retUnstructured := &unstructured.Unstructured{}
+ if err := c.client.scheme.Convert(obj, retUnstructured, nil); err != nil {
+ return nil, err
+ }
+ entireList, err := retUnstructured.ToList()
+ if err != nil {
+ return nil, err
+ }
+
+ list := &unstructured.UnstructuredList{}
+ list.SetResourceVersion(entireList.GetResourceVersion())
+ for i := range entireList.Items {
+ item := &entireList.Items[i]
+ metadata, err := meta.Accessor(item)
+ if err != nil {
+ return nil, err
+ }
+ if label.Matches(labels.Set(metadata.GetLabels())) {
+ list.Items = append(list.Items, *item)
+ }
+ }
+ return list, nil
+}
+
+func (c *dynamicResourceClient) Watch(opts metav1.ListOptions) (watch.Interface, error) {
+ switch {
+ case len(c.namespace) == 0:
+ return c.client.Fake.
+ InvokesWatch(testing.NewRootWatchAction(c.resource, opts))
+
+ case len(c.namespace) > 0:
+ return c.client.Fake.
+ InvokesWatch(testing.NewWatchAction(c.resource, c.namespace, opts))
+
+ }
+
+ panic("math broke")
+}
+
+// TODO: opts are currently ignored.
+func (c *dynamicResourceClient) Patch(name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (*unstructured.Unstructured, error) {
+ var uncastRet runtime.Object
+ var err error
+ switch {
+ case len(c.namespace) == 0 && len(subresources) == 0:
+ uncastRet, err = c.client.Fake.
+ Invokes(testing.NewRootPatchAction(c.resource, name, pt, data), &metav1.Status{Status: "dynamic patch fail"})
+
+ case len(c.namespace) == 0 && len(subresources) > 0:
+ uncastRet, err = c.client.Fake.
+ Invokes(testing.NewRootPatchSubresourceAction(c.resource, name, pt, data, subresources...), &metav1.Status{Status: "dynamic patch fail"})
+
+ case len(c.namespace) > 0 && len(subresources) == 0:
+ uncastRet, err = c.client.Fake.
+ Invokes(testing.NewPatchAction(c.resource, c.namespace, name, pt, data), &metav1.Status{Status: "dynamic patch fail"})
+
+ case len(c.namespace) > 0 && len(subresources) > 0:
+ uncastRet, err = c.client.Fake.
+ Invokes(testing.NewPatchSubresourceAction(c.resource, c.namespace, name, pt, data, subresources...), &metav1.Status{Status: "dynamic patch fail"})
+
+ }
+
+ if err != nil {
+ return nil, err
+ }
+ if uncastRet == nil {
+ return nil, err
+ }
+
+ ret := &unstructured.Unstructured{}
+ if err := c.client.scheme.Convert(uncastRet, ret, nil); err != nil {
+ return nil, err
+ }
+ return ret, err
+}
diff --git a/vendor/k8s.io/client-go/dynamic/interface.go b/vendor/k8s.io/client-go/dynamic/interface.go
new file mode 100644
index 000000000..70756a4f5
--- /dev/null
+++ b/vendor/k8s.io/client-go/dynamic/interface.go
@@ -0,0 +1,59 @@
+/*
+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 dynamic
+
+import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/apimachinery/pkg/types"
+ "k8s.io/apimachinery/pkg/watch"
+)
+
+type Interface interface {
+ Resource(resource schema.GroupVersionResource) NamespaceableResourceInterface
+}
+
+type ResourceInterface interface {
+ Create(obj *unstructured.Unstructured, options metav1.CreateOptions, subresources ...string) (*unstructured.Unstructured, error)
+ Update(obj *unstructured.Unstructured, options metav1.UpdateOptions, subresources ...string) (*unstructured.Unstructured, error)
+ UpdateStatus(obj *unstructured.Unstructured, options metav1.UpdateOptions) (*unstructured.Unstructured, error)
+ Delete(name string, options *metav1.DeleteOptions, subresources ...string) error
+ DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error
+ Get(name string, options metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, error)
+ List(opts metav1.ListOptions) (*unstructured.UnstructuredList, error)
+ Watch(opts metav1.ListOptions) (watch.Interface, error)
+ Patch(name string, pt types.PatchType, data []byte, options metav1.PatchOptions, subresources ...string) (*unstructured.Unstructured, error)
+}
+
+type NamespaceableResourceInterface interface {
+ Namespace(string) ResourceInterface
+ ResourceInterface
+}
+
+// APIPathResolverFunc knows how to convert a groupVersion to its API path. The Kind field is optional.
+// TODO find a better place to move this for existing callers
+type APIPathResolverFunc func(kind schema.GroupVersionKind) string
+
+// LegacyAPIPathResolverFunc can resolve paths properly with the legacy API.
+// TODO find a better place to move this for existing callers
+func LegacyAPIPathResolverFunc(kind schema.GroupVersionKind) string {
+ if len(kind.Group) == 0 {
+ return "/api"
+ }
+ return "/apis"
+}
diff --git a/vendor/k8s.io/client-go/dynamic/scheme.go b/vendor/k8s.io/client-go/dynamic/scheme.go
new file mode 100644
index 000000000..4596104d8
--- /dev/null
+++ b/vendor/k8s.io/client-go/dynamic/scheme.go
@@ -0,0 +1,102 @@
+/*
+Copyright 2018 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 dynamic
+
+import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/apimachinery/pkg/runtime/serializer"
+ "k8s.io/apimachinery/pkg/runtime/serializer/json"
+ "k8s.io/apimachinery/pkg/runtime/serializer/versioning"
+)
+
+var watchScheme = runtime.NewScheme()
+var basicScheme = runtime.NewScheme()
+var deleteScheme = runtime.NewScheme()
+var parameterScheme = runtime.NewScheme()
+var deleteOptionsCodec = serializer.NewCodecFactory(deleteScheme)
+var dynamicParameterCodec = runtime.NewParameterCodec(parameterScheme)
+
+var versionV1 = schema.GroupVersion{Version: "v1"}
+
+func init() {
+ metav1.AddToGroupVersion(watchScheme, versionV1)
+ metav1.AddToGroupVersion(basicScheme, versionV1)
+ metav1.AddToGroupVersion(parameterScheme, versionV1)
+ metav1.AddToGroupVersion(deleteScheme, versionV1)
+}
+
+var watchJsonSerializerInfo = runtime.SerializerInfo{
+ MediaType: "application/json",
+ MediaTypeType: "application",
+ MediaTypeSubType: "json",
+ EncodesAsText: true,
+ Serializer: json.NewSerializer(json.DefaultMetaFactory, watchScheme, watchScheme, false),
+ PrettySerializer: json.NewSerializer(json.DefaultMetaFactory, watchScheme, watchScheme, true),
+ StreamSerializer: &runtime.StreamSerializerInfo{
+ EncodesAsText: true,
+ Serializer: json.NewSerializer(json.DefaultMetaFactory, watchScheme, watchScheme, false),
+ Framer: json.Framer,
+ },
+}
+
+// watchNegotiatedSerializer is used to read the wrapper of the watch stream
+type watchNegotiatedSerializer struct{}
+
+var watchNegotiatedSerializerInstance = watchNegotiatedSerializer{}
+
+func (s watchNegotiatedSerializer) SupportedMediaTypes() []runtime.SerializerInfo {
+ return []runtime.SerializerInfo{watchJsonSerializerInfo}
+}
+
+func (s watchNegotiatedSerializer) EncoderForVersion(encoder runtime.Encoder, gv runtime.GroupVersioner) runtime.Encoder {
+ return versioning.NewDefaultingCodecForScheme(watchScheme, encoder, nil, gv, nil)
+}
+
+func (s watchNegotiatedSerializer) DecoderToVersion(decoder runtime.Decoder, gv runtime.GroupVersioner) runtime.Decoder {
+ return versioning.NewDefaultingCodecForScheme(watchScheme, nil, decoder, nil, gv)
+}
+
+// basicNegotiatedSerializer is used to handle discovery and error handling serialization
+type basicNegotiatedSerializer struct{}
+
+func (s basicNegotiatedSerializer) SupportedMediaTypes() []runtime.SerializerInfo {
+ return []runtime.SerializerInfo{
+ {
+ MediaType: "application/json",
+ MediaTypeType: "application",
+ MediaTypeSubType: "json",
+ EncodesAsText: true,
+ Serializer: json.NewSerializer(json.DefaultMetaFactory, basicScheme, basicScheme, false),
+ PrettySerializer: json.NewSerializer(json.DefaultMetaFactory, basicScheme, basicScheme, true),
+ StreamSerializer: &runtime.StreamSerializerInfo{
+ EncodesAsText: true,
+ Serializer: json.NewSerializer(json.DefaultMetaFactory, basicScheme, basicScheme, false),
+ Framer: json.Framer,
+ },
+ },
+ }
+}
+
+func (s basicNegotiatedSerializer) EncoderForVersion(encoder runtime.Encoder, gv runtime.GroupVersioner) runtime.Encoder {
+ return versioning.NewDefaultingCodecForScheme(watchScheme, encoder, nil, gv, nil)
+}
+
+func (s basicNegotiatedSerializer) DecoderToVersion(decoder runtime.Decoder, gv runtime.GroupVersioner) runtime.Decoder {
+ return versioning.NewDefaultingCodecForScheme(watchScheme, nil, decoder, nil, gv)
+}
diff --git a/vendor/k8s.io/client-go/dynamic/simple.go b/vendor/k8s.io/client-go/dynamic/simple.go
new file mode 100644
index 000000000..4e0ef5a7d
--- /dev/null
+++ b/vendor/k8s.io/client-go/dynamic/simple.go
@@ -0,0 +1,355 @@
+/*
+Copyright 2018 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 dynamic
+
+import (
+ "fmt"
+ "io"
+
+ "k8s.io/apimachinery/pkg/api/meta"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/apimachinery/pkg/runtime/serializer/streaming"
+ "k8s.io/apimachinery/pkg/types"
+ "k8s.io/apimachinery/pkg/watch"
+ "k8s.io/client-go/rest"
+)
+
+type dynamicClient struct {
+ client *rest.RESTClient
+}
+
+var _ Interface = &dynamicClient{}
+
+// ConfigFor returns a copy of the provided config with the
+// appropriate dynamic client defaults set.
+func ConfigFor(inConfig *rest.Config) *rest.Config {
+ config := rest.CopyConfig(inConfig)
+ config.AcceptContentTypes = "application/json"
+ config.ContentType = "application/json"
+ config.NegotiatedSerializer = basicNegotiatedSerializer{} // this gets used for discovery and error handling types
+ if config.UserAgent == "" {
+ config.UserAgent = rest.DefaultKubernetesUserAgent()
+ }
+ return config
+}
+
+// NewForConfigOrDie creates a new Interface for the given config and
+// panics if there is an error in the config.
+func NewForConfigOrDie(c *rest.Config) Interface {
+ ret, err := NewForConfig(c)
+ if err != nil {
+ panic(err)
+ }
+ return ret
+}
+
+// NewForConfig creates a new dynamic client or returns an error.
+func NewForConfig(inConfig *rest.Config) (Interface, error) {
+ config := ConfigFor(inConfig)
+ // for serializing the options
+ config.GroupVersion = &schema.GroupVersion{}
+ config.APIPath = "/if-you-see-this-search-for-the-break"
+
+ restClient, err := rest.RESTClientFor(config)
+ if err != nil {
+ return nil, err
+ }
+
+ return &dynamicClient{client: restClient}, nil
+}
+
+type dynamicResourceClient struct {
+ client *dynamicClient
+ namespace string
+ resource schema.GroupVersionResource
+}
+
+func (c *dynamicClient) Resource(resource schema.GroupVersionResource) NamespaceableResourceInterface {
+ return &dynamicResourceClient{client: c, resource: resource}
+}
+
+func (c *dynamicResourceClient) Namespace(ns string) ResourceInterface {
+ ret := *c
+ ret.namespace = ns
+ return &ret
+}
+
+func (c *dynamicResourceClient) Create(obj *unstructured.Unstructured, opts metav1.CreateOptions, subresources ...string) (*unstructured.Unstructured, error) {
+ outBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj)
+ if err != nil {
+ return nil, err
+ }
+ name := ""
+ if len(subresources) > 0 {
+ accessor, err := meta.Accessor(obj)
+ if err != nil {
+ return nil, err
+ }
+ name = accessor.GetName()
+ if len(name) == 0 {
+ return nil, fmt.Errorf("name is required")
+ }
+ }
+
+ result := c.client.client.
+ Post().
+ AbsPath(append(c.makeURLSegments(name), subresources...)...).
+ Body(outBytes).
+ SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).
+ Do()
+ if err := result.Error(); err != nil {
+ return nil, err
+ }
+
+ retBytes, err := result.Raw()
+ if err != nil {
+ return nil, err
+ }
+ uncastObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, retBytes)
+ if err != nil {
+ return nil, err
+ }
+ return uncastObj.(*unstructured.Unstructured), nil
+}
+
+func (c *dynamicResourceClient) Update(obj *unstructured.Unstructured, opts metav1.UpdateOptions, subresources ...string) (*unstructured.Unstructured, error) {
+ accessor, err := meta.Accessor(obj)
+ if err != nil {
+ return nil, err
+ }
+ name := accessor.GetName()
+ if len(name) == 0 {
+ return nil, fmt.Errorf("name is required")
+ }
+ outBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj)
+ if err != nil {
+ return nil, err
+ }
+
+ result := c.client.client.
+ Put().
+ AbsPath(append(c.makeURLSegments(name), subresources...)...).
+ Body(outBytes).
+ SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).
+ Do()
+ if err := result.Error(); err != nil {
+ return nil, err
+ }
+
+ retBytes, err := result.Raw()
+ if err != nil {
+ return nil, err
+ }
+ uncastObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, retBytes)
+ if err != nil {
+ return nil, err
+ }
+ return uncastObj.(*unstructured.Unstructured), nil
+}
+
+func (c *dynamicResourceClient) UpdateStatus(obj *unstructured.Unstructured, opts metav1.UpdateOptions) (*unstructured.Unstructured, error) {
+ accessor, err := meta.Accessor(obj)
+ if err != nil {
+ return nil, err
+ }
+ name := accessor.GetName()
+ if len(name) == 0 {
+ return nil, fmt.Errorf("name is required")
+ }
+
+ outBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj)
+ if err != nil {
+ return nil, err
+ }
+
+ result := c.client.client.
+ Put().
+ AbsPath(append(c.makeURLSegments(name), "status")...).
+ Body(outBytes).
+ SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).
+ Do()
+ if err := result.Error(); err != nil {
+ return nil, err
+ }
+
+ retBytes, err := result.Raw()
+ if err != nil {
+ return nil, err
+ }
+ uncastObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, retBytes)
+ if err != nil {
+ return nil, err
+ }
+ return uncastObj.(*unstructured.Unstructured), nil
+}
+
+func (c *dynamicResourceClient) Delete(name string, opts *metav1.DeleteOptions, subresources ...string) error {
+ if len(name) == 0 {
+ return fmt.Errorf("name is required")
+ }
+ if opts == nil {
+ opts = &metav1.DeleteOptions{}
+ }
+ deleteOptionsByte, err := runtime.Encode(deleteOptionsCodec.LegacyCodec(schema.GroupVersion{Version: "v1"}), opts)
+ if err != nil {
+ return err
+ }
+
+ result := c.client.client.
+ Delete().
+ AbsPath(append(c.makeURLSegments(name), subresources...)...).
+ Body(deleteOptionsByte).
+ Do()
+ return result.Error()
+}
+
+func (c *dynamicResourceClient) DeleteCollection(opts *metav1.DeleteOptions, listOptions metav1.ListOptions) error {
+ if opts == nil {
+ opts = &metav1.DeleteOptions{}
+ }
+ deleteOptionsByte, err := runtime.Encode(deleteOptionsCodec.LegacyCodec(schema.GroupVersion{Version: "v1"}), opts)
+ if err != nil {
+ return err
+ }
+
+ result := c.client.client.
+ Delete().
+ AbsPath(c.makeURLSegments("")...).
+ Body(deleteOptionsByte).
+ SpecificallyVersionedParams(&listOptions, dynamicParameterCodec, versionV1).
+ Do()
+ return result.Error()
+}
+
+func (c *dynamicResourceClient) Get(name string, opts metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, error) {
+ if len(name) == 0 {
+ return nil, fmt.Errorf("name is required")
+ }
+ result := c.client.client.Get().AbsPath(append(c.makeURLSegments(name), subresources...)...).SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).Do()
+ if err := result.Error(); err != nil {
+ return nil, err
+ }
+ retBytes, err := result.Raw()
+ if err != nil {
+ return nil, err
+ }
+ uncastObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, retBytes)
+ if err != nil {
+ return nil, err
+ }
+ return uncastObj.(*unstructured.Unstructured), nil
+}
+
+func (c *dynamicResourceClient) List(opts metav1.ListOptions) (*unstructured.UnstructuredList, error) {
+ result := c.client.client.Get().AbsPath(c.makeURLSegments("")...).SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).Do()
+ if err := result.Error(); err != nil {
+ return nil, err
+ }
+ retBytes, err := result.Raw()
+ if err != nil {
+ return nil, err
+ }
+ uncastObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, retBytes)
+ if err != nil {
+ return nil, err
+ }
+ if list, ok := uncastObj.(*unstructured.UnstructuredList); ok {
+ return list, nil
+ }
+
+ list, err := uncastObj.(*unstructured.Unstructured).ToList()
+ if err != nil {
+ return nil, err
+ }
+ return list, nil
+}
+
+func (c *dynamicResourceClient) Watch(opts metav1.ListOptions) (watch.Interface, error) {
+ internalGV := schema.GroupVersions{
+ {Group: c.resource.Group, Version: runtime.APIVersionInternal},
+ // always include the legacy group as a decoding target to handle non-error `Status` return types
+ {Group: "", Version: runtime.APIVersionInternal},
+ }
+ s := &rest.Serializers{
+ Encoder: watchNegotiatedSerializerInstance.EncoderForVersion(watchJsonSerializerInfo.Serializer, c.resource.GroupVersion()),
+ Decoder: watchNegotiatedSerializerInstance.DecoderToVersion(watchJsonSerializerInfo.Serializer, internalGV),
+
+ RenegotiatedDecoder: func(contentType string, params map[string]string) (runtime.Decoder, error) {
+ return watchNegotiatedSerializerInstance.DecoderToVersion(watchJsonSerializerInfo.Serializer, internalGV), nil
+ },
+ StreamingSerializer: watchJsonSerializerInfo.StreamSerializer.Serializer,
+ Framer: watchJsonSerializerInfo.StreamSerializer.Framer,
+ }
+
+ wrappedDecoderFn := func(body io.ReadCloser) streaming.Decoder {
+ framer := s.Framer.NewFrameReader(body)
+ return streaming.NewDecoder(framer, s.StreamingSerializer)
+ }
+
+ opts.Watch = true
+ return c.client.client.Get().AbsPath(c.makeURLSegments("")...).
+ SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).
+ WatchWithSpecificDecoders(wrappedDecoderFn, unstructured.UnstructuredJSONScheme)
+}
+
+func (c *dynamicResourceClient) Patch(name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (*unstructured.Unstructured, error) {
+ if len(name) == 0 {
+ return nil, fmt.Errorf("name is required")
+ }
+ result := c.client.client.
+ Patch(pt).
+ AbsPath(append(c.makeURLSegments(name), subresources...)...).
+ Body(data).
+ SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).
+ Do()
+ if err := result.Error(); err != nil {
+ return nil, err
+ }
+ retBytes, err := result.Raw()
+ if err != nil {
+ return nil, err
+ }
+ uncastObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, retBytes)
+ if err != nil {
+ return nil, err
+ }
+ return uncastObj.(*unstructured.Unstructured), nil
+}
+
+func (c *dynamicResourceClient) makeURLSegments(name string) []string {
+ url := []string{}
+ if len(c.resource.Group) == 0 {
+ url = append(url, "api")
+ } else {
+ url = append(url, "apis", c.resource.Group)
+ }
+ url = append(url, c.resource.Version)
+
+ if len(c.namespace) > 0 {
+ url = append(url, "namespaces", c.namespace)
+ }
+ url = append(url, c.resource.Resource)
+
+ if len(name) > 0 {
+ url = append(url, name)
+ }
+
+ return url
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/fake/clientset_generated.go b/vendor/k8s.io/client-go/kubernetes/fake/clientset_generated.go
new file mode 100644
index 000000000..0c73d00ab
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/fake/clientset_generated.go
@@ -0,0 +1,327 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/watch"
+ "k8s.io/client-go/discovery"
+ fakediscovery "k8s.io/client-go/discovery/fake"
+ clientset "k8s.io/client-go/kubernetes"
+ admissionregistrationv1beta1 "k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1"
+ fakeadmissionregistrationv1beta1 "k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake"
+ appsv1 "k8s.io/client-go/kubernetes/typed/apps/v1"
+ fakeappsv1 "k8s.io/client-go/kubernetes/typed/apps/v1/fake"
+ appsv1beta1 "k8s.io/client-go/kubernetes/typed/apps/v1beta1"
+ fakeappsv1beta1 "k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake"
+ appsv1beta2 "k8s.io/client-go/kubernetes/typed/apps/v1beta2"
+ fakeappsv1beta2 "k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake"
+ auditregistrationv1alpha1 "k8s.io/client-go/kubernetes/typed/auditregistration/v1alpha1"
+ fakeauditregistrationv1alpha1 "k8s.io/client-go/kubernetes/typed/auditregistration/v1alpha1/fake"
+ authenticationv1 "k8s.io/client-go/kubernetes/typed/authentication/v1"
+ fakeauthenticationv1 "k8s.io/client-go/kubernetes/typed/authentication/v1/fake"
+ authenticationv1beta1 "k8s.io/client-go/kubernetes/typed/authentication/v1beta1"
+ fakeauthenticationv1beta1 "k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake"
+ authorizationv1 "k8s.io/client-go/kubernetes/typed/authorization/v1"
+ fakeauthorizationv1 "k8s.io/client-go/kubernetes/typed/authorization/v1/fake"
+ authorizationv1beta1 "k8s.io/client-go/kubernetes/typed/authorization/v1beta1"
+ fakeauthorizationv1beta1 "k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake"
+ autoscalingv1 "k8s.io/client-go/kubernetes/typed/autoscaling/v1"
+ fakeautoscalingv1 "k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake"
+ autoscalingv2beta1 "k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1"
+ fakeautoscalingv2beta1 "k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake"
+ autoscalingv2beta2 "k8s.io/client-go/kubernetes/typed/autoscaling/v2beta2"
+ fakeautoscalingv2beta2 "k8s.io/client-go/kubernetes/typed/autoscaling/v2beta2/fake"
+ batchv1 "k8s.io/client-go/kubernetes/typed/batch/v1"
+ fakebatchv1 "k8s.io/client-go/kubernetes/typed/batch/v1/fake"
+ batchv1beta1 "k8s.io/client-go/kubernetes/typed/batch/v1beta1"
+ fakebatchv1beta1 "k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake"
+ batchv2alpha1 "k8s.io/client-go/kubernetes/typed/batch/v2alpha1"
+ fakebatchv2alpha1 "k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake"
+ certificatesv1beta1 "k8s.io/client-go/kubernetes/typed/certificates/v1beta1"
+ fakecertificatesv1beta1 "k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake"
+ coordinationv1 "k8s.io/client-go/kubernetes/typed/coordination/v1"
+ fakecoordinationv1 "k8s.io/client-go/kubernetes/typed/coordination/v1/fake"
+ coordinationv1beta1 "k8s.io/client-go/kubernetes/typed/coordination/v1beta1"
+ fakecoordinationv1beta1 "k8s.io/client-go/kubernetes/typed/coordination/v1beta1/fake"
+ corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
+ fakecorev1 "k8s.io/client-go/kubernetes/typed/core/v1/fake"
+ eventsv1beta1 "k8s.io/client-go/kubernetes/typed/events/v1beta1"
+ fakeeventsv1beta1 "k8s.io/client-go/kubernetes/typed/events/v1beta1/fake"
+ extensionsv1beta1 "k8s.io/client-go/kubernetes/typed/extensions/v1beta1"
+ fakeextensionsv1beta1 "k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake"
+ networkingv1 "k8s.io/client-go/kubernetes/typed/networking/v1"
+ fakenetworkingv1 "k8s.io/client-go/kubernetes/typed/networking/v1/fake"
+ networkingv1beta1 "k8s.io/client-go/kubernetes/typed/networking/v1beta1"
+ fakenetworkingv1beta1 "k8s.io/client-go/kubernetes/typed/networking/v1beta1/fake"
+ nodev1alpha1 "k8s.io/client-go/kubernetes/typed/node/v1alpha1"
+ fakenodev1alpha1 "k8s.io/client-go/kubernetes/typed/node/v1alpha1/fake"
+ nodev1beta1 "k8s.io/client-go/kubernetes/typed/node/v1beta1"
+ fakenodev1beta1 "k8s.io/client-go/kubernetes/typed/node/v1beta1/fake"
+ policyv1beta1 "k8s.io/client-go/kubernetes/typed/policy/v1beta1"
+ fakepolicyv1beta1 "k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake"
+ rbacv1 "k8s.io/client-go/kubernetes/typed/rbac/v1"
+ fakerbacv1 "k8s.io/client-go/kubernetes/typed/rbac/v1/fake"
+ rbacv1alpha1 "k8s.io/client-go/kubernetes/typed/rbac/v1alpha1"
+ fakerbacv1alpha1 "k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake"
+ rbacv1beta1 "k8s.io/client-go/kubernetes/typed/rbac/v1beta1"
+ fakerbacv1beta1 "k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake"
+ schedulingv1 "k8s.io/client-go/kubernetes/typed/scheduling/v1"
+ fakeschedulingv1 "k8s.io/client-go/kubernetes/typed/scheduling/v1/fake"
+ schedulingv1alpha1 "k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1"
+ fakeschedulingv1alpha1 "k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake"
+ schedulingv1beta1 "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1"
+ fakeschedulingv1beta1 "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake"
+ settingsv1alpha1 "k8s.io/client-go/kubernetes/typed/settings/v1alpha1"
+ fakesettingsv1alpha1 "k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake"
+ storagev1 "k8s.io/client-go/kubernetes/typed/storage/v1"
+ fakestoragev1 "k8s.io/client-go/kubernetes/typed/storage/v1/fake"
+ storagev1alpha1 "k8s.io/client-go/kubernetes/typed/storage/v1alpha1"
+ fakestoragev1alpha1 "k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake"
+ storagev1beta1 "k8s.io/client-go/kubernetes/typed/storage/v1beta1"
+ fakestoragev1beta1 "k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake"
+ "k8s.io/client-go/testing"
+)
+
+// NewSimpleClientset returns a clientset that will respond with the provided objects.
+// It's backed by a very simple object tracker that processes creates, updates and deletions as-is,
+// without applying any validations and/or defaults. It shouldn't be considered a replacement
+// for a real clientset and is mostly useful in simple unit tests.
+func NewSimpleClientset(objects ...runtime.Object) *Clientset {
+ o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder())
+ for _, obj := range objects {
+ if err := o.Add(obj); err != nil {
+ panic(err)
+ }
+ }
+
+ cs := &Clientset{tracker: o}
+ cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake}
+ cs.AddReactor("*", "*", testing.ObjectReaction(o))
+ cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) {
+ gvr := action.GetResource()
+ ns := action.GetNamespace()
+ watch, err := o.Watch(gvr, ns)
+ if err != nil {
+ return false, nil, err
+ }
+ return true, watch, nil
+ })
+
+ return cs
+}
+
+// Clientset implements clientset.Interface. Meant to be embedded into a
+// struct to get a default implementation. This makes faking out just the method
+// you want to test easier.
+type Clientset struct {
+ testing.Fake
+ discovery *fakediscovery.FakeDiscovery
+ tracker testing.ObjectTracker
+}
+
+func (c *Clientset) Discovery() discovery.DiscoveryInterface {
+ return c.discovery
+}
+
+func (c *Clientset) Tracker() testing.ObjectTracker {
+ return c.tracker
+}
+
+var _ clientset.Interface = &Clientset{}
+
+// AdmissionregistrationV1beta1 retrieves the AdmissionregistrationV1beta1Client
+func (c *Clientset) AdmissionregistrationV1beta1() admissionregistrationv1beta1.AdmissionregistrationV1beta1Interface {
+ return &fakeadmissionregistrationv1beta1.FakeAdmissionregistrationV1beta1{Fake: &c.Fake}
+}
+
+// AppsV1 retrieves the AppsV1Client
+func (c *Clientset) AppsV1() appsv1.AppsV1Interface {
+ return &fakeappsv1.FakeAppsV1{Fake: &c.Fake}
+}
+
+// AppsV1beta1 retrieves the AppsV1beta1Client
+func (c *Clientset) AppsV1beta1() appsv1beta1.AppsV1beta1Interface {
+ return &fakeappsv1beta1.FakeAppsV1beta1{Fake: &c.Fake}
+}
+
+// AppsV1beta2 retrieves the AppsV1beta2Client
+func (c *Clientset) AppsV1beta2() appsv1beta2.AppsV1beta2Interface {
+ return &fakeappsv1beta2.FakeAppsV1beta2{Fake: &c.Fake}
+}
+
+// AuditregistrationV1alpha1 retrieves the AuditregistrationV1alpha1Client
+func (c *Clientset) AuditregistrationV1alpha1() auditregistrationv1alpha1.AuditregistrationV1alpha1Interface {
+ return &fakeauditregistrationv1alpha1.FakeAuditregistrationV1alpha1{Fake: &c.Fake}
+}
+
+// AuthenticationV1 retrieves the AuthenticationV1Client
+func (c *Clientset) AuthenticationV1() authenticationv1.AuthenticationV1Interface {
+ return &fakeauthenticationv1.FakeAuthenticationV1{Fake: &c.Fake}
+}
+
+// AuthenticationV1beta1 retrieves the AuthenticationV1beta1Client
+func (c *Clientset) AuthenticationV1beta1() authenticationv1beta1.AuthenticationV1beta1Interface {
+ return &fakeauthenticationv1beta1.FakeAuthenticationV1beta1{Fake: &c.Fake}
+}
+
+// AuthorizationV1 retrieves the AuthorizationV1Client
+func (c *Clientset) AuthorizationV1() authorizationv1.AuthorizationV1Interface {
+ return &fakeauthorizationv1.FakeAuthorizationV1{Fake: &c.Fake}
+}
+
+// AuthorizationV1beta1 retrieves the AuthorizationV1beta1Client
+func (c *Clientset) AuthorizationV1beta1() authorizationv1beta1.AuthorizationV1beta1Interface {
+ return &fakeauthorizationv1beta1.FakeAuthorizationV1beta1{Fake: &c.Fake}
+}
+
+// AutoscalingV1 retrieves the AutoscalingV1Client
+func (c *Clientset) AutoscalingV1() autoscalingv1.AutoscalingV1Interface {
+ return &fakeautoscalingv1.FakeAutoscalingV1{Fake: &c.Fake}
+}
+
+// AutoscalingV2beta1 retrieves the AutoscalingV2beta1Client
+func (c *Clientset) AutoscalingV2beta1() autoscalingv2beta1.AutoscalingV2beta1Interface {
+ return &fakeautoscalingv2beta1.FakeAutoscalingV2beta1{Fake: &c.Fake}
+}
+
+// AutoscalingV2beta2 retrieves the AutoscalingV2beta2Client
+func (c *Clientset) AutoscalingV2beta2() autoscalingv2beta2.AutoscalingV2beta2Interface {
+ return &fakeautoscalingv2beta2.FakeAutoscalingV2beta2{Fake: &c.Fake}
+}
+
+// BatchV1 retrieves the BatchV1Client
+func (c *Clientset) BatchV1() batchv1.BatchV1Interface {
+ return &fakebatchv1.FakeBatchV1{Fake: &c.Fake}
+}
+
+// BatchV1beta1 retrieves the BatchV1beta1Client
+func (c *Clientset) BatchV1beta1() batchv1beta1.BatchV1beta1Interface {
+ return &fakebatchv1beta1.FakeBatchV1beta1{Fake: &c.Fake}
+}
+
+// BatchV2alpha1 retrieves the BatchV2alpha1Client
+func (c *Clientset) BatchV2alpha1() batchv2alpha1.BatchV2alpha1Interface {
+ return &fakebatchv2alpha1.FakeBatchV2alpha1{Fake: &c.Fake}
+}
+
+// CertificatesV1beta1 retrieves the CertificatesV1beta1Client
+func (c *Clientset) CertificatesV1beta1() certificatesv1beta1.CertificatesV1beta1Interface {
+ return &fakecertificatesv1beta1.FakeCertificatesV1beta1{Fake: &c.Fake}
+}
+
+// CoordinationV1beta1 retrieves the CoordinationV1beta1Client
+func (c *Clientset) CoordinationV1beta1() coordinationv1beta1.CoordinationV1beta1Interface {
+ return &fakecoordinationv1beta1.FakeCoordinationV1beta1{Fake: &c.Fake}
+}
+
+// CoordinationV1 retrieves the CoordinationV1Client
+func (c *Clientset) CoordinationV1() coordinationv1.CoordinationV1Interface {
+ return &fakecoordinationv1.FakeCoordinationV1{Fake: &c.Fake}
+}
+
+// CoreV1 retrieves the CoreV1Client
+func (c *Clientset) CoreV1() corev1.CoreV1Interface {
+ return &fakecorev1.FakeCoreV1{Fake: &c.Fake}
+}
+
+// EventsV1beta1 retrieves the EventsV1beta1Client
+func (c *Clientset) EventsV1beta1() eventsv1beta1.EventsV1beta1Interface {
+ return &fakeeventsv1beta1.FakeEventsV1beta1{Fake: &c.Fake}
+}
+
+// ExtensionsV1beta1 retrieves the ExtensionsV1beta1Client
+func (c *Clientset) ExtensionsV1beta1() extensionsv1beta1.ExtensionsV1beta1Interface {
+ return &fakeextensionsv1beta1.FakeExtensionsV1beta1{Fake: &c.Fake}
+}
+
+// NetworkingV1 retrieves the NetworkingV1Client
+func (c *Clientset) NetworkingV1() networkingv1.NetworkingV1Interface {
+ return &fakenetworkingv1.FakeNetworkingV1{Fake: &c.Fake}
+}
+
+// NetworkingV1beta1 retrieves the NetworkingV1beta1Client
+func (c *Clientset) NetworkingV1beta1() networkingv1beta1.NetworkingV1beta1Interface {
+ return &fakenetworkingv1beta1.FakeNetworkingV1beta1{Fake: &c.Fake}
+}
+
+// NodeV1alpha1 retrieves the NodeV1alpha1Client
+func (c *Clientset) NodeV1alpha1() nodev1alpha1.NodeV1alpha1Interface {
+ return &fakenodev1alpha1.FakeNodeV1alpha1{Fake: &c.Fake}
+}
+
+// NodeV1beta1 retrieves the NodeV1beta1Client
+func (c *Clientset) NodeV1beta1() nodev1beta1.NodeV1beta1Interface {
+ return &fakenodev1beta1.FakeNodeV1beta1{Fake: &c.Fake}
+}
+
+// PolicyV1beta1 retrieves the PolicyV1beta1Client
+func (c *Clientset) PolicyV1beta1() policyv1beta1.PolicyV1beta1Interface {
+ return &fakepolicyv1beta1.FakePolicyV1beta1{Fake: &c.Fake}
+}
+
+// RbacV1 retrieves the RbacV1Client
+func (c *Clientset) RbacV1() rbacv1.RbacV1Interface {
+ return &fakerbacv1.FakeRbacV1{Fake: &c.Fake}
+}
+
+// RbacV1beta1 retrieves the RbacV1beta1Client
+func (c *Clientset) RbacV1beta1() rbacv1beta1.RbacV1beta1Interface {
+ return &fakerbacv1beta1.FakeRbacV1beta1{Fake: &c.Fake}
+}
+
+// RbacV1alpha1 retrieves the RbacV1alpha1Client
+func (c *Clientset) RbacV1alpha1() rbacv1alpha1.RbacV1alpha1Interface {
+ return &fakerbacv1alpha1.FakeRbacV1alpha1{Fake: &c.Fake}
+}
+
+// SchedulingV1alpha1 retrieves the SchedulingV1alpha1Client
+func (c *Clientset) SchedulingV1alpha1() schedulingv1alpha1.SchedulingV1alpha1Interface {
+ return &fakeschedulingv1alpha1.FakeSchedulingV1alpha1{Fake: &c.Fake}
+}
+
+// SchedulingV1beta1 retrieves the SchedulingV1beta1Client
+func (c *Clientset) SchedulingV1beta1() schedulingv1beta1.SchedulingV1beta1Interface {
+ return &fakeschedulingv1beta1.FakeSchedulingV1beta1{Fake: &c.Fake}
+}
+
+// SchedulingV1 retrieves the SchedulingV1Client
+func (c *Clientset) SchedulingV1() schedulingv1.SchedulingV1Interface {
+ return &fakeschedulingv1.FakeSchedulingV1{Fake: &c.Fake}
+}
+
+// SettingsV1alpha1 retrieves the SettingsV1alpha1Client
+func (c *Clientset) SettingsV1alpha1() settingsv1alpha1.SettingsV1alpha1Interface {
+ return &fakesettingsv1alpha1.FakeSettingsV1alpha1{Fake: &c.Fake}
+}
+
+// StorageV1beta1 retrieves the StorageV1beta1Client
+func (c *Clientset) StorageV1beta1() storagev1beta1.StorageV1beta1Interface {
+ return &fakestoragev1beta1.FakeStorageV1beta1{Fake: &c.Fake}
+}
+
+// StorageV1 retrieves the StorageV1Client
+func (c *Clientset) StorageV1() storagev1.StorageV1Interface {
+ return &fakestoragev1.FakeStorageV1{Fake: &c.Fake}
+}
+
+// StorageV1alpha1 retrieves the StorageV1alpha1Client
+func (c *Clientset) StorageV1alpha1() storagev1alpha1.StorageV1alpha1Interface {
+ return &fakestoragev1alpha1.FakeStorageV1alpha1{Fake: &c.Fake}
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/fake/doc.go
new file mode 100644
index 000000000..9b99e7167
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// This package has the automatically generated fake clientset.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/fake/register.go b/vendor/k8s.io/client-go/kubernetes/fake/register.go
new file mode 100644
index 000000000..62e07afba
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/fake/register.go
@@ -0,0 +1,126 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ admissionregistrationv1beta1 "k8s.io/api/admissionregistration/v1beta1"
+ appsv1 "k8s.io/api/apps/v1"
+ appsv1beta1 "k8s.io/api/apps/v1beta1"
+ appsv1beta2 "k8s.io/api/apps/v1beta2"
+ auditregistrationv1alpha1 "k8s.io/api/auditregistration/v1alpha1"
+ authenticationv1 "k8s.io/api/authentication/v1"
+ authenticationv1beta1 "k8s.io/api/authentication/v1beta1"
+ authorizationv1 "k8s.io/api/authorization/v1"
+ authorizationv1beta1 "k8s.io/api/authorization/v1beta1"
+ autoscalingv1 "k8s.io/api/autoscaling/v1"
+ autoscalingv2beta1 "k8s.io/api/autoscaling/v2beta1"
+ autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2"
+ batchv1 "k8s.io/api/batch/v1"
+ batchv1beta1 "k8s.io/api/batch/v1beta1"
+ batchv2alpha1 "k8s.io/api/batch/v2alpha1"
+ certificatesv1beta1 "k8s.io/api/certificates/v1beta1"
+ coordinationv1 "k8s.io/api/coordination/v1"
+ coordinationv1beta1 "k8s.io/api/coordination/v1beta1"
+ corev1 "k8s.io/api/core/v1"
+ eventsv1beta1 "k8s.io/api/events/v1beta1"
+ extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
+ networkingv1 "k8s.io/api/networking/v1"
+ networkingv1beta1 "k8s.io/api/networking/v1beta1"
+ nodev1alpha1 "k8s.io/api/node/v1alpha1"
+ nodev1beta1 "k8s.io/api/node/v1beta1"
+ policyv1beta1 "k8s.io/api/policy/v1beta1"
+ rbacv1 "k8s.io/api/rbac/v1"
+ rbacv1alpha1 "k8s.io/api/rbac/v1alpha1"
+ rbacv1beta1 "k8s.io/api/rbac/v1beta1"
+ schedulingv1 "k8s.io/api/scheduling/v1"
+ schedulingv1alpha1 "k8s.io/api/scheduling/v1alpha1"
+ schedulingv1beta1 "k8s.io/api/scheduling/v1beta1"
+ settingsv1alpha1 "k8s.io/api/settings/v1alpha1"
+ storagev1 "k8s.io/api/storage/v1"
+ storagev1alpha1 "k8s.io/api/storage/v1alpha1"
+ storagev1beta1 "k8s.io/api/storage/v1beta1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ runtime "k8s.io/apimachinery/pkg/runtime"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ serializer "k8s.io/apimachinery/pkg/runtime/serializer"
+ utilruntime "k8s.io/apimachinery/pkg/util/runtime"
+)
+
+var scheme = runtime.NewScheme()
+var codecs = serializer.NewCodecFactory(scheme)
+var parameterCodec = runtime.NewParameterCodec(scheme)
+var localSchemeBuilder = runtime.SchemeBuilder{
+ admissionregistrationv1beta1.AddToScheme,
+ appsv1.AddToScheme,
+ appsv1beta1.AddToScheme,
+ appsv1beta2.AddToScheme,
+ auditregistrationv1alpha1.AddToScheme,
+ authenticationv1.AddToScheme,
+ authenticationv1beta1.AddToScheme,
+ authorizationv1.AddToScheme,
+ authorizationv1beta1.AddToScheme,
+ autoscalingv1.AddToScheme,
+ autoscalingv2beta1.AddToScheme,
+ autoscalingv2beta2.AddToScheme,
+ batchv1.AddToScheme,
+ batchv1beta1.AddToScheme,
+ batchv2alpha1.AddToScheme,
+ certificatesv1beta1.AddToScheme,
+ coordinationv1beta1.AddToScheme,
+ coordinationv1.AddToScheme,
+ corev1.AddToScheme,
+ eventsv1beta1.AddToScheme,
+ extensionsv1beta1.AddToScheme,
+ networkingv1.AddToScheme,
+ networkingv1beta1.AddToScheme,
+ nodev1alpha1.AddToScheme,
+ nodev1beta1.AddToScheme,
+ policyv1beta1.AddToScheme,
+ rbacv1.AddToScheme,
+ rbacv1beta1.AddToScheme,
+ rbacv1alpha1.AddToScheme,
+ schedulingv1alpha1.AddToScheme,
+ schedulingv1beta1.AddToScheme,
+ schedulingv1.AddToScheme,
+ settingsv1alpha1.AddToScheme,
+ storagev1beta1.AddToScheme,
+ storagev1.AddToScheme,
+ storagev1alpha1.AddToScheme,
+}
+
+// AddToScheme adds all types of this clientset into the given scheme. This allows composition
+// of clientsets, like in:
+//
+// import (
+// "k8s.io/client-go/kubernetes"
+// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
+// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
+// )
+//
+// kclientset, _ := kubernetes.NewForConfig(c)
+// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
+//
+// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
+// correctly.
+var AddToScheme = localSchemeBuilder.AddToScheme
+
+func init() {
+ v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"})
+ utilruntime.Must(AddToScheme(scheme))
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_admissionregistration_client.go b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_admissionregistration_client.go
new file mode 100644
index 000000000..1a988ddba
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_admissionregistration_client.go
@@ -0,0 +1,44 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeAdmissionregistrationV1beta1 struct {
+ *testing.Fake
+}
+
+func (c *FakeAdmissionregistrationV1beta1) MutatingWebhookConfigurations() v1beta1.MutatingWebhookConfigurationInterface {
+ return &FakeMutatingWebhookConfigurations{c}
+}
+
+func (c *FakeAdmissionregistrationV1beta1) ValidatingWebhookConfigurations() v1beta1.ValidatingWebhookConfigurationInterface {
+ return &FakeValidatingWebhookConfigurations{c}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeAdmissionregistrationV1beta1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_mutatingwebhookconfiguration.go b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_mutatingwebhookconfiguration.go
new file mode 100644
index 000000000..d2177bad5
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_mutatingwebhookconfiguration.go
@@ -0,0 +1,120 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/api/admissionregistration/v1beta1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeMutatingWebhookConfigurations implements MutatingWebhookConfigurationInterface
+type FakeMutatingWebhookConfigurations struct {
+ Fake *FakeAdmissionregistrationV1beta1
+}
+
+var mutatingwebhookconfigurationsResource = schema.GroupVersionResource{Group: "admissionregistration.k8s.io", Version: "v1beta1", Resource: "mutatingwebhookconfigurations"}
+
+var mutatingwebhookconfigurationsKind = schema.GroupVersionKind{Group: "admissionregistration.k8s.io", Version: "v1beta1", Kind: "MutatingWebhookConfiguration"}
+
+// Get takes name of the mutatingWebhookConfiguration, and returns the corresponding mutatingWebhookConfiguration object, and an error if there is any.
+func (c *FakeMutatingWebhookConfigurations) Get(name string, options v1.GetOptions) (result *v1beta1.MutatingWebhookConfiguration, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootGetAction(mutatingwebhookconfigurationsResource, name), &v1beta1.MutatingWebhookConfiguration{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.MutatingWebhookConfiguration), err
+}
+
+// List takes label and field selectors, and returns the list of MutatingWebhookConfigurations that match those selectors.
+func (c *FakeMutatingWebhookConfigurations) List(opts v1.ListOptions) (result *v1beta1.MutatingWebhookConfigurationList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootListAction(mutatingwebhookconfigurationsResource, mutatingwebhookconfigurationsKind, opts), &v1beta1.MutatingWebhookConfigurationList{})
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta1.MutatingWebhookConfigurationList{ListMeta: obj.(*v1beta1.MutatingWebhookConfigurationList).ListMeta}
+ for _, item := range obj.(*v1beta1.MutatingWebhookConfigurationList).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 mutatingWebhookConfigurations.
+func (c *FakeMutatingWebhookConfigurations) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewRootWatchAction(mutatingwebhookconfigurationsResource, opts))
+}
+
+// Create takes the representation of a mutatingWebhookConfiguration and creates it. Returns the server's representation of the mutatingWebhookConfiguration, and an error, if there is any.
+func (c *FakeMutatingWebhookConfigurations) Create(mutatingWebhookConfiguration *v1beta1.MutatingWebhookConfiguration) (result *v1beta1.MutatingWebhookConfiguration, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootCreateAction(mutatingwebhookconfigurationsResource, mutatingWebhookConfiguration), &v1beta1.MutatingWebhookConfiguration{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.MutatingWebhookConfiguration), err
+}
+
+// Update takes the representation of a mutatingWebhookConfiguration and updates it. Returns the server's representation of the mutatingWebhookConfiguration, and an error, if there is any.
+func (c *FakeMutatingWebhookConfigurations) Update(mutatingWebhookConfiguration *v1beta1.MutatingWebhookConfiguration) (result *v1beta1.MutatingWebhookConfiguration, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateAction(mutatingwebhookconfigurationsResource, mutatingWebhookConfiguration), &v1beta1.MutatingWebhookConfiguration{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.MutatingWebhookConfiguration), err
+}
+
+// Delete takes name of the mutatingWebhookConfiguration and deletes it. Returns an error if one occurs.
+func (c *FakeMutatingWebhookConfigurations) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewRootDeleteAction(mutatingwebhookconfigurationsResource, name), &v1beta1.MutatingWebhookConfiguration{})
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeMutatingWebhookConfigurations) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewRootDeleteCollectionAction(mutatingwebhookconfigurationsResource, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta1.MutatingWebhookConfigurationList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched mutatingWebhookConfiguration.
+func (c *FakeMutatingWebhookConfigurations) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.MutatingWebhookConfiguration, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootPatchSubresourceAction(mutatingwebhookconfigurationsResource, name, pt, data, subresources...), &v1beta1.MutatingWebhookConfiguration{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.MutatingWebhookConfiguration), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_validatingwebhookconfiguration.go b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_validatingwebhookconfiguration.go
new file mode 100644
index 000000000..6be2b3938
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_validatingwebhookconfiguration.go
@@ -0,0 +1,120 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/api/admissionregistration/v1beta1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeValidatingWebhookConfigurations implements ValidatingWebhookConfigurationInterface
+type FakeValidatingWebhookConfigurations struct {
+ Fake *FakeAdmissionregistrationV1beta1
+}
+
+var validatingwebhookconfigurationsResource = schema.GroupVersionResource{Group: "admissionregistration.k8s.io", Version: "v1beta1", Resource: "validatingwebhookconfigurations"}
+
+var validatingwebhookconfigurationsKind = schema.GroupVersionKind{Group: "admissionregistration.k8s.io", Version: "v1beta1", Kind: "ValidatingWebhookConfiguration"}
+
+// Get takes name of the validatingWebhookConfiguration, and returns the corresponding validatingWebhookConfiguration object, and an error if there is any.
+func (c *FakeValidatingWebhookConfigurations) Get(name string, options v1.GetOptions) (result *v1beta1.ValidatingWebhookConfiguration, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootGetAction(validatingwebhookconfigurationsResource, name), &v1beta1.ValidatingWebhookConfiguration{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.ValidatingWebhookConfiguration), err
+}
+
+// List takes label and field selectors, and returns the list of ValidatingWebhookConfigurations that match those selectors.
+func (c *FakeValidatingWebhookConfigurations) List(opts v1.ListOptions) (result *v1beta1.ValidatingWebhookConfigurationList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootListAction(validatingwebhookconfigurationsResource, validatingwebhookconfigurationsKind, opts), &v1beta1.ValidatingWebhookConfigurationList{})
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta1.ValidatingWebhookConfigurationList{ListMeta: obj.(*v1beta1.ValidatingWebhookConfigurationList).ListMeta}
+ for _, item := range obj.(*v1beta1.ValidatingWebhookConfigurationList).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 validatingWebhookConfigurations.
+func (c *FakeValidatingWebhookConfigurations) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewRootWatchAction(validatingwebhookconfigurationsResource, opts))
+}
+
+// Create takes the representation of a validatingWebhookConfiguration and creates it. Returns the server's representation of the validatingWebhookConfiguration, and an error, if there is any.
+func (c *FakeValidatingWebhookConfigurations) Create(validatingWebhookConfiguration *v1beta1.ValidatingWebhookConfiguration) (result *v1beta1.ValidatingWebhookConfiguration, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootCreateAction(validatingwebhookconfigurationsResource, validatingWebhookConfiguration), &v1beta1.ValidatingWebhookConfiguration{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.ValidatingWebhookConfiguration), err
+}
+
+// Update takes the representation of a validatingWebhookConfiguration and updates it. Returns the server's representation of the validatingWebhookConfiguration, and an error, if there is any.
+func (c *FakeValidatingWebhookConfigurations) Update(validatingWebhookConfiguration *v1beta1.ValidatingWebhookConfiguration) (result *v1beta1.ValidatingWebhookConfiguration, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateAction(validatingwebhookconfigurationsResource, validatingWebhookConfiguration), &v1beta1.ValidatingWebhookConfiguration{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.ValidatingWebhookConfiguration), err
+}
+
+// Delete takes name of the validatingWebhookConfiguration and deletes it. Returns an error if one occurs.
+func (c *FakeValidatingWebhookConfigurations) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewRootDeleteAction(validatingwebhookconfigurationsResource, name), &v1beta1.ValidatingWebhookConfiguration{})
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeValidatingWebhookConfigurations) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewRootDeleteCollectionAction(validatingwebhookconfigurationsResource, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta1.ValidatingWebhookConfigurationList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched validatingWebhookConfiguration.
+func (c *FakeValidatingWebhookConfigurations) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.ValidatingWebhookConfiguration, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootPatchSubresourceAction(validatingwebhookconfigurationsResource, name, pt, data, subresources...), &v1beta1.ValidatingWebhookConfiguration{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.ValidatingWebhookConfiguration), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_apps_client.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_apps_client.go
new file mode 100644
index 000000000..458df0fa3
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_apps_client.go
@@ -0,0 +1,56 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1 "k8s.io/client-go/kubernetes/typed/apps/v1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeAppsV1 struct {
+ *testing.Fake
+}
+
+func (c *FakeAppsV1) ControllerRevisions(namespace string) v1.ControllerRevisionInterface {
+ return &FakeControllerRevisions{c, namespace}
+}
+
+func (c *FakeAppsV1) DaemonSets(namespace string) v1.DaemonSetInterface {
+ return &FakeDaemonSets{c, namespace}
+}
+
+func (c *FakeAppsV1) Deployments(namespace string) v1.DeploymentInterface {
+ return &FakeDeployments{c, namespace}
+}
+
+func (c *FakeAppsV1) ReplicaSets(namespace string) v1.ReplicaSetInterface {
+ return &FakeReplicaSets{c, namespace}
+}
+
+func (c *FakeAppsV1) StatefulSets(namespace string) v1.StatefulSetInterface {
+ return &FakeStatefulSets{c, namespace}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeAppsV1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_controllerrevision.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_controllerrevision.go
new file mode 100644
index 000000000..eb38bca41
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_controllerrevision.go
@@ -0,0 +1,128 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ appsv1 "k8s.io/api/apps/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeControllerRevisions implements ControllerRevisionInterface
+type FakeControllerRevisions struct {
+ Fake *FakeAppsV1
+ ns string
+}
+
+var controllerrevisionsResource = schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "controllerrevisions"}
+
+var controllerrevisionsKind = schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "ControllerRevision"}
+
+// Get takes name of the controllerRevision, and returns the corresponding controllerRevision object, and an error if there is any.
+func (c *FakeControllerRevisions) Get(name string, options v1.GetOptions) (result *appsv1.ControllerRevision, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(controllerrevisionsResource, c.ns, name), &appsv1.ControllerRevision{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*appsv1.ControllerRevision), err
+}
+
+// List takes label and field selectors, and returns the list of ControllerRevisions that match those selectors.
+func (c *FakeControllerRevisions) List(opts v1.ListOptions) (result *appsv1.ControllerRevisionList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(controllerrevisionsResource, controllerrevisionsKind, c.ns, opts), &appsv1.ControllerRevisionList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &appsv1.ControllerRevisionList{ListMeta: obj.(*appsv1.ControllerRevisionList).ListMeta}
+ for _, item := range obj.(*appsv1.ControllerRevisionList).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 controllerRevisions.
+func (c *FakeControllerRevisions) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(controllerrevisionsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a controllerRevision and creates it. Returns the server's representation of the controllerRevision, and an error, if there is any.
+func (c *FakeControllerRevisions) Create(controllerRevision *appsv1.ControllerRevision) (result *appsv1.ControllerRevision, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(controllerrevisionsResource, c.ns, controllerRevision), &appsv1.ControllerRevision{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*appsv1.ControllerRevision), err
+}
+
+// Update takes the representation of a controllerRevision and updates it. Returns the server's representation of the controllerRevision, and an error, if there is any.
+func (c *FakeControllerRevisions) Update(controllerRevision *appsv1.ControllerRevision) (result *appsv1.ControllerRevision, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(controllerrevisionsResource, c.ns, controllerRevision), &appsv1.ControllerRevision{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*appsv1.ControllerRevision), err
+}
+
+// Delete takes name of the controllerRevision and deletes it. Returns an error if one occurs.
+func (c *FakeControllerRevisions) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(controllerrevisionsResource, c.ns, name), &appsv1.ControllerRevision{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeControllerRevisions) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(controllerrevisionsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &appsv1.ControllerRevisionList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched controllerRevision.
+func (c *FakeControllerRevisions) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *appsv1.ControllerRevision, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(controllerrevisionsResource, c.ns, name, pt, data, subresources...), &appsv1.ControllerRevision{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*appsv1.ControllerRevision), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_daemonset.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_daemonset.go
new file mode 100644
index 000000000..c06336e97
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_daemonset.go
@@ -0,0 +1,140 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ appsv1 "k8s.io/api/apps/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeDaemonSets implements DaemonSetInterface
+type FakeDaemonSets struct {
+ Fake *FakeAppsV1
+ ns string
+}
+
+var daemonsetsResource = schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "daemonsets"}
+
+var daemonsetsKind = schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "DaemonSet"}
+
+// Get takes name of the daemonSet, and returns the corresponding daemonSet object, and an error if there is any.
+func (c *FakeDaemonSets) Get(name string, options v1.GetOptions) (result *appsv1.DaemonSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(daemonsetsResource, c.ns, name), &appsv1.DaemonSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*appsv1.DaemonSet), err
+}
+
+// List takes label and field selectors, and returns the list of DaemonSets that match those selectors.
+func (c *FakeDaemonSets) List(opts v1.ListOptions) (result *appsv1.DaemonSetList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(daemonsetsResource, daemonsetsKind, c.ns, opts), &appsv1.DaemonSetList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &appsv1.DaemonSetList{ListMeta: obj.(*appsv1.DaemonSetList).ListMeta}
+ for _, item := range obj.(*appsv1.DaemonSetList).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 daemonSets.
+func (c *FakeDaemonSets) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(daemonsetsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a daemonSet and creates it. Returns the server's representation of the daemonSet, and an error, if there is any.
+func (c *FakeDaemonSets) Create(daemonSet *appsv1.DaemonSet) (result *appsv1.DaemonSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(daemonsetsResource, c.ns, daemonSet), &appsv1.DaemonSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*appsv1.DaemonSet), err
+}
+
+// Update takes the representation of a daemonSet and updates it. Returns the server's representation of the daemonSet, and an error, if there is any.
+func (c *FakeDaemonSets) Update(daemonSet *appsv1.DaemonSet) (result *appsv1.DaemonSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(daemonsetsResource, c.ns, daemonSet), &appsv1.DaemonSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*appsv1.DaemonSet), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeDaemonSets) UpdateStatus(daemonSet *appsv1.DaemonSet) (*appsv1.DaemonSet, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(daemonsetsResource, "status", c.ns, daemonSet), &appsv1.DaemonSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*appsv1.DaemonSet), err
+}
+
+// Delete takes name of the daemonSet and deletes it. Returns an error if one occurs.
+func (c *FakeDaemonSets) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(daemonsetsResource, c.ns, name), &appsv1.DaemonSet{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeDaemonSets) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(daemonsetsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &appsv1.DaemonSetList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched daemonSet.
+func (c *FakeDaemonSets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *appsv1.DaemonSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(daemonsetsResource, c.ns, name, pt, data, subresources...), &appsv1.DaemonSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*appsv1.DaemonSet), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_deployment.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_deployment.go
new file mode 100644
index 000000000..6a8cb379d
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_deployment.go
@@ -0,0 +1,163 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ appsv1 "k8s.io/api/apps/v1"
+ autoscalingv1 "k8s.io/api/autoscaling/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeDeployments implements DeploymentInterface
+type FakeDeployments struct {
+ Fake *FakeAppsV1
+ ns string
+}
+
+var deploymentsResource = schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"}
+
+var deploymentsKind = schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "Deployment"}
+
+// Get takes name of the deployment, and returns the corresponding deployment object, and an error if there is any.
+func (c *FakeDeployments) Get(name string, options v1.GetOptions) (result *appsv1.Deployment, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(deploymentsResource, c.ns, name), &appsv1.Deployment{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*appsv1.Deployment), err
+}
+
+// List takes label and field selectors, and returns the list of Deployments that match those selectors.
+func (c *FakeDeployments) List(opts v1.ListOptions) (result *appsv1.DeploymentList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(deploymentsResource, deploymentsKind, c.ns, opts), &appsv1.DeploymentList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &appsv1.DeploymentList{ListMeta: obj.(*appsv1.DeploymentList).ListMeta}
+ for _, item := range obj.(*appsv1.DeploymentList).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 deployments.
+func (c *FakeDeployments) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(deploymentsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a deployment and creates it. Returns the server's representation of the deployment, and an error, if there is any.
+func (c *FakeDeployments) Create(deployment *appsv1.Deployment) (result *appsv1.Deployment, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(deploymentsResource, c.ns, deployment), &appsv1.Deployment{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*appsv1.Deployment), err
+}
+
+// Update takes the representation of a deployment and updates it. Returns the server's representation of the deployment, and an error, if there is any.
+func (c *FakeDeployments) Update(deployment *appsv1.Deployment) (result *appsv1.Deployment, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(deploymentsResource, c.ns, deployment), &appsv1.Deployment{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*appsv1.Deployment), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeDeployments) UpdateStatus(deployment *appsv1.Deployment) (*appsv1.Deployment, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(deploymentsResource, "status", c.ns, deployment), &appsv1.Deployment{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*appsv1.Deployment), err
+}
+
+// Delete takes name of the deployment and deletes it. Returns an error if one occurs.
+func (c *FakeDeployments) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(deploymentsResource, c.ns, name), &appsv1.Deployment{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeDeployments) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(deploymentsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &appsv1.DeploymentList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched deployment.
+func (c *FakeDeployments) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *appsv1.Deployment, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(deploymentsResource, c.ns, name, pt, data, subresources...), &appsv1.Deployment{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*appsv1.Deployment), err
+}
+
+// GetScale takes name of the deployment, and returns the corresponding scale object, and an error if there is any.
+func (c *FakeDeployments) GetScale(deploymentName string, options v1.GetOptions) (result *autoscalingv1.Scale, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetSubresourceAction(deploymentsResource, c.ns, "scale", deploymentName), &autoscalingv1.Scale{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*autoscalingv1.Scale), err
+}
+
+// UpdateScale takes the representation of a scale and updates it. Returns the server's representation of the scale, and an error, if there is any.
+func (c *FakeDeployments) UpdateScale(deploymentName string, scale *autoscalingv1.Scale) (result *autoscalingv1.Scale, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(deploymentsResource, "scale", c.ns, scale), &autoscalingv1.Scale{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*autoscalingv1.Scale), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_replicaset.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_replicaset.go
new file mode 100644
index 000000000..e871f82f7
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_replicaset.go
@@ -0,0 +1,163 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ appsv1 "k8s.io/api/apps/v1"
+ autoscalingv1 "k8s.io/api/autoscaling/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeReplicaSets implements ReplicaSetInterface
+type FakeReplicaSets struct {
+ Fake *FakeAppsV1
+ ns string
+}
+
+var replicasetsResource = schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "replicasets"}
+
+var replicasetsKind = schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "ReplicaSet"}
+
+// Get takes name of the replicaSet, and returns the corresponding replicaSet object, and an error if there is any.
+func (c *FakeReplicaSets) Get(name string, options v1.GetOptions) (result *appsv1.ReplicaSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(replicasetsResource, c.ns, name), &appsv1.ReplicaSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*appsv1.ReplicaSet), err
+}
+
+// List takes label and field selectors, and returns the list of ReplicaSets that match those selectors.
+func (c *FakeReplicaSets) List(opts v1.ListOptions) (result *appsv1.ReplicaSetList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(replicasetsResource, replicasetsKind, c.ns, opts), &appsv1.ReplicaSetList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &appsv1.ReplicaSetList{ListMeta: obj.(*appsv1.ReplicaSetList).ListMeta}
+ for _, item := range obj.(*appsv1.ReplicaSetList).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 replicaSets.
+func (c *FakeReplicaSets) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(replicasetsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a replicaSet and creates it. Returns the server's representation of the replicaSet, and an error, if there is any.
+func (c *FakeReplicaSets) Create(replicaSet *appsv1.ReplicaSet) (result *appsv1.ReplicaSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(replicasetsResource, c.ns, replicaSet), &appsv1.ReplicaSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*appsv1.ReplicaSet), err
+}
+
+// Update takes the representation of a replicaSet and updates it. Returns the server's representation of the replicaSet, and an error, if there is any.
+func (c *FakeReplicaSets) Update(replicaSet *appsv1.ReplicaSet) (result *appsv1.ReplicaSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(replicasetsResource, c.ns, replicaSet), &appsv1.ReplicaSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*appsv1.ReplicaSet), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeReplicaSets) UpdateStatus(replicaSet *appsv1.ReplicaSet) (*appsv1.ReplicaSet, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(replicasetsResource, "status", c.ns, replicaSet), &appsv1.ReplicaSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*appsv1.ReplicaSet), err
+}
+
+// Delete takes name of the replicaSet and deletes it. Returns an error if one occurs.
+func (c *FakeReplicaSets) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(replicasetsResource, c.ns, name), &appsv1.ReplicaSet{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeReplicaSets) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(replicasetsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &appsv1.ReplicaSetList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched replicaSet.
+func (c *FakeReplicaSets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *appsv1.ReplicaSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(replicasetsResource, c.ns, name, pt, data, subresources...), &appsv1.ReplicaSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*appsv1.ReplicaSet), err
+}
+
+// GetScale takes name of the replicaSet, and returns the corresponding scale object, and an error if there is any.
+func (c *FakeReplicaSets) GetScale(replicaSetName string, options v1.GetOptions) (result *autoscalingv1.Scale, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetSubresourceAction(replicasetsResource, c.ns, "scale", replicaSetName), &autoscalingv1.Scale{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*autoscalingv1.Scale), err
+}
+
+// UpdateScale takes the representation of a scale and updates it. Returns the server's representation of the scale, and an error, if there is any.
+func (c *FakeReplicaSets) UpdateScale(replicaSetName string, scale *autoscalingv1.Scale) (result *autoscalingv1.Scale, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(replicasetsResource, "scale", c.ns, scale), &autoscalingv1.Scale{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*autoscalingv1.Scale), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_statefulset.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_statefulset.go
new file mode 100644
index 000000000..83e80bff4
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_statefulset.go
@@ -0,0 +1,163 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ appsv1 "k8s.io/api/apps/v1"
+ autoscalingv1 "k8s.io/api/autoscaling/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeStatefulSets implements StatefulSetInterface
+type FakeStatefulSets struct {
+ Fake *FakeAppsV1
+ ns string
+}
+
+var statefulsetsResource = schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "statefulsets"}
+
+var statefulsetsKind = schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "StatefulSet"}
+
+// Get takes name of the statefulSet, and returns the corresponding statefulSet object, and an error if there is any.
+func (c *FakeStatefulSets) Get(name string, options v1.GetOptions) (result *appsv1.StatefulSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(statefulsetsResource, c.ns, name), &appsv1.StatefulSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*appsv1.StatefulSet), err
+}
+
+// List takes label and field selectors, and returns the list of StatefulSets that match those selectors.
+func (c *FakeStatefulSets) List(opts v1.ListOptions) (result *appsv1.StatefulSetList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(statefulsetsResource, statefulsetsKind, c.ns, opts), &appsv1.StatefulSetList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &appsv1.StatefulSetList{ListMeta: obj.(*appsv1.StatefulSetList).ListMeta}
+ for _, item := range obj.(*appsv1.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))
+
+}
+
+// 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 *FakeStatefulSets) Create(statefulSet *appsv1.StatefulSet) (result *appsv1.StatefulSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(statefulsetsResource, c.ns, statefulSet), &appsv1.StatefulSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*appsv1.StatefulSet), err
+}
+
+// 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 *FakeStatefulSets) Update(statefulSet *appsv1.StatefulSet) (result *appsv1.StatefulSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(statefulsetsResource, c.ns, statefulSet), &appsv1.StatefulSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*appsv1.StatefulSet), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeStatefulSets) UpdateStatus(statefulSet *appsv1.StatefulSet) (*appsv1.StatefulSet, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(statefulsetsResource, "status", c.ns, statefulSet), &appsv1.StatefulSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*appsv1.StatefulSet), err
+}
+
+// Delete takes name of the statefulSet and deletes it. Returns an error if one occurs.
+func (c *FakeStatefulSets) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(statefulsetsResource, c.ns, name), &appsv1.StatefulSet{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeStatefulSets) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(statefulsetsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &appsv1.StatefulSetList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched statefulSet.
+func (c *FakeStatefulSets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *appsv1.StatefulSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(statefulsetsResource, c.ns, name, pt, data, subresources...), &appsv1.StatefulSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*appsv1.StatefulSet), err
+}
+
+// GetScale takes name of the statefulSet, and returns the corresponding scale object, and an error if there is any.
+func (c *FakeStatefulSets) GetScale(statefulSetName string, options v1.GetOptions) (result *autoscalingv1.Scale, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetSubresourceAction(statefulsetsResource, c.ns, "scale", statefulSetName), &autoscalingv1.Scale{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*autoscalingv1.Scale), err
+}
+
+// UpdateScale takes the representation of a scale and updates it. Returns the server's representation of the scale, and an error, if there is any.
+func (c *FakeStatefulSets) UpdateScale(statefulSetName string, scale *autoscalingv1.Scale) (result *autoscalingv1.Scale, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(statefulsetsResource, "scale", c.ns, scale), &autoscalingv1.Scale{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*autoscalingv1.Scale), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_apps_client.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_apps_client.go
new file mode 100644
index 000000000..8e65d78d2
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_apps_client.go
@@ -0,0 +1,48 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/client-go/kubernetes/typed/apps/v1beta1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeAppsV1beta1 struct {
+ *testing.Fake
+}
+
+func (c *FakeAppsV1beta1) ControllerRevisions(namespace string) v1beta1.ControllerRevisionInterface {
+ return &FakeControllerRevisions{c, namespace}
+}
+
+func (c *FakeAppsV1beta1) Deployments(namespace string) v1beta1.DeploymentInterface {
+ return &FakeDeployments{c, namespace}
+}
+
+func (c *FakeAppsV1beta1) StatefulSets(namespace string) v1beta1.StatefulSetInterface {
+ return &FakeStatefulSets{c, namespace}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeAppsV1beta1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_controllerrevision.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_controllerrevision.go
new file mode 100644
index 000000000..8e339d78b
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_controllerrevision.go
@@ -0,0 +1,128 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/api/apps/v1beta1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeControllerRevisions implements ControllerRevisionInterface
+type FakeControllerRevisions struct {
+ Fake *FakeAppsV1beta1
+ ns string
+}
+
+var controllerrevisionsResource = schema.GroupVersionResource{Group: "apps", Version: "v1beta1", Resource: "controllerrevisions"}
+
+var controllerrevisionsKind = schema.GroupVersionKind{Group: "apps", Version: "v1beta1", Kind: "ControllerRevision"}
+
+// Get takes name of the controllerRevision, and returns the corresponding controllerRevision object, and an error if there is any.
+func (c *FakeControllerRevisions) Get(name string, options v1.GetOptions) (result *v1beta1.ControllerRevision, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(controllerrevisionsResource, c.ns, name), &v1beta1.ControllerRevision{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.ControllerRevision), err
+}
+
+// List takes label and field selectors, and returns the list of ControllerRevisions that match those selectors.
+func (c *FakeControllerRevisions) List(opts v1.ListOptions) (result *v1beta1.ControllerRevisionList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(controllerrevisionsResource, controllerrevisionsKind, c.ns, opts), &v1beta1.ControllerRevisionList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta1.ControllerRevisionList{ListMeta: obj.(*v1beta1.ControllerRevisionList).ListMeta}
+ for _, item := range obj.(*v1beta1.ControllerRevisionList).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 controllerRevisions.
+func (c *FakeControllerRevisions) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(controllerrevisionsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a controllerRevision and creates it. Returns the server's representation of the controllerRevision, and an error, if there is any.
+func (c *FakeControllerRevisions) Create(controllerRevision *v1beta1.ControllerRevision) (result *v1beta1.ControllerRevision, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(controllerrevisionsResource, c.ns, controllerRevision), &v1beta1.ControllerRevision{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.ControllerRevision), err
+}
+
+// Update takes the representation of a controllerRevision and updates it. Returns the server's representation of the controllerRevision, and an error, if there is any.
+func (c *FakeControllerRevisions) Update(controllerRevision *v1beta1.ControllerRevision) (result *v1beta1.ControllerRevision, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(controllerrevisionsResource, c.ns, controllerRevision), &v1beta1.ControllerRevision{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.ControllerRevision), err
+}
+
+// Delete takes name of the controllerRevision and deletes it. Returns an error if one occurs.
+func (c *FakeControllerRevisions) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(controllerrevisionsResource, c.ns, name), &v1beta1.ControllerRevision{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeControllerRevisions) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(controllerrevisionsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta1.ControllerRevisionList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched controllerRevision.
+func (c *FakeControllerRevisions) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.ControllerRevision, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(controllerrevisionsResource, c.ns, name, pt, data, subresources...), &v1beta1.ControllerRevision{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.ControllerRevision), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_deployment.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_deployment.go
new file mode 100644
index 000000000..c33baba58
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_deployment.go
@@ -0,0 +1,140 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/api/apps/v1beta1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeDeployments implements DeploymentInterface
+type FakeDeployments struct {
+ Fake *FakeAppsV1beta1
+ ns string
+}
+
+var deploymentsResource = schema.GroupVersionResource{Group: "apps", Version: "v1beta1", Resource: "deployments"}
+
+var deploymentsKind = schema.GroupVersionKind{Group: "apps", Version: "v1beta1", Kind: "Deployment"}
+
+// Get takes name of the deployment, and returns the corresponding deployment object, and an error if there is any.
+func (c *FakeDeployments) Get(name string, options v1.GetOptions) (result *v1beta1.Deployment, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(deploymentsResource, c.ns, name), &v1beta1.Deployment{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Deployment), err
+}
+
+// List takes label and field selectors, and returns the list of Deployments that match those selectors.
+func (c *FakeDeployments) List(opts v1.ListOptions) (result *v1beta1.DeploymentList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(deploymentsResource, deploymentsKind, c.ns, opts), &v1beta1.DeploymentList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta1.DeploymentList{ListMeta: obj.(*v1beta1.DeploymentList).ListMeta}
+ for _, item := range obj.(*v1beta1.DeploymentList).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 deployments.
+func (c *FakeDeployments) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(deploymentsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a deployment and creates it. Returns the server's representation of the deployment, and an error, if there is any.
+func (c *FakeDeployments) Create(deployment *v1beta1.Deployment) (result *v1beta1.Deployment, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(deploymentsResource, c.ns, deployment), &v1beta1.Deployment{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Deployment), err
+}
+
+// Update takes the representation of a deployment and updates it. Returns the server's representation of the deployment, and an error, if there is any.
+func (c *FakeDeployments) Update(deployment *v1beta1.Deployment) (result *v1beta1.Deployment, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(deploymentsResource, c.ns, deployment), &v1beta1.Deployment{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Deployment), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeDeployments) UpdateStatus(deployment *v1beta1.Deployment) (*v1beta1.Deployment, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(deploymentsResource, "status", c.ns, deployment), &v1beta1.Deployment{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Deployment), err
+}
+
+// Delete takes name of the deployment and deletes it. Returns an error if one occurs.
+func (c *FakeDeployments) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(deploymentsResource, c.ns, name), &v1beta1.Deployment{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeDeployments) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(deploymentsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta1.DeploymentList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched deployment.
+func (c *FakeDeployments) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.Deployment, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(deploymentsResource, c.ns, name, pt, data, subresources...), &v1beta1.Deployment{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Deployment), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_statefulset.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_statefulset.go
new file mode 100644
index 000000000..754da5fba
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_statefulset.go
@@ -0,0 +1,140 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/api/apps/v1beta1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeStatefulSets implements StatefulSetInterface
+type FakeStatefulSets struct {
+ Fake *FakeAppsV1beta1
+ ns string
+}
+
+var statefulsetsResource = schema.GroupVersionResource{Group: "apps", Version: "v1beta1", Resource: "statefulsets"}
+
+var statefulsetsKind = schema.GroupVersionKind{Group: "apps", Version: "v1beta1", Kind: "StatefulSet"}
+
+// Get takes name of the statefulSet, and returns the corresponding statefulSet object, and an error if there is any.
+func (c *FakeStatefulSets) Get(name string, options v1.GetOptions) (result *v1beta1.StatefulSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(statefulsetsResource, c.ns, name), &v1beta1.StatefulSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.StatefulSet), err
+}
+
+// List takes label and field selectors, and returns the list of StatefulSets that match those selectors.
+func (c *FakeStatefulSets) List(opts v1.ListOptions) (result *v1beta1.StatefulSetList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(statefulsetsResource, statefulsetsKind, c.ns, opts), &v1beta1.StatefulSetList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta1.StatefulSetList{ListMeta: obj.(*v1beta1.StatefulSetList).ListMeta}
+ for _, item := range obj.(*v1beta1.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))
+
+}
+
+// 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 *FakeStatefulSets) Create(statefulSet *v1beta1.StatefulSet) (result *v1beta1.StatefulSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(statefulsetsResource, c.ns, statefulSet), &v1beta1.StatefulSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.StatefulSet), err
+}
+
+// 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 *FakeStatefulSets) Update(statefulSet *v1beta1.StatefulSet) (result *v1beta1.StatefulSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(statefulsetsResource, c.ns, statefulSet), &v1beta1.StatefulSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.StatefulSet), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeStatefulSets) UpdateStatus(statefulSet *v1beta1.StatefulSet) (*v1beta1.StatefulSet, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(statefulsetsResource, "status", c.ns, statefulSet), &v1beta1.StatefulSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.StatefulSet), err
+}
+
+// Delete takes name of the statefulSet and deletes it. Returns an error if one occurs.
+func (c *FakeStatefulSets) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(statefulsetsResource, c.ns, name), &v1beta1.StatefulSet{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeStatefulSets) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(statefulsetsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta1.StatefulSetList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched statefulSet.
+func (c *FakeStatefulSets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.StatefulSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(statefulsetsResource, c.ns, name, pt, data, subresources...), &v1beta1.StatefulSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.StatefulSet), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_apps_client.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_apps_client.go
new file mode 100644
index 000000000..0ec34a2cd
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_apps_client.go
@@ -0,0 +1,56 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta2 "k8s.io/client-go/kubernetes/typed/apps/v1beta2"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeAppsV1beta2 struct {
+ *testing.Fake
+}
+
+func (c *FakeAppsV1beta2) ControllerRevisions(namespace string) v1beta2.ControllerRevisionInterface {
+ return &FakeControllerRevisions{c, namespace}
+}
+
+func (c *FakeAppsV1beta2) DaemonSets(namespace string) v1beta2.DaemonSetInterface {
+ return &FakeDaemonSets{c, namespace}
+}
+
+func (c *FakeAppsV1beta2) Deployments(namespace string) v1beta2.DeploymentInterface {
+ return &FakeDeployments{c, namespace}
+}
+
+func (c *FakeAppsV1beta2) ReplicaSets(namespace string) v1beta2.ReplicaSetInterface {
+ return &FakeReplicaSets{c, namespace}
+}
+
+func (c *FakeAppsV1beta2) StatefulSets(namespace string) v1beta2.StatefulSetInterface {
+ return &FakeStatefulSets{c, namespace}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeAppsV1beta2) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_controllerrevision.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_controllerrevision.go
new file mode 100644
index 000000000..197f190cb
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_controllerrevision.go
@@ -0,0 +1,128 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta2 "k8s.io/api/apps/v1beta2"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeControllerRevisions implements ControllerRevisionInterface
+type FakeControllerRevisions struct {
+ Fake *FakeAppsV1beta2
+ ns string
+}
+
+var controllerrevisionsResource = schema.GroupVersionResource{Group: "apps", Version: "v1beta2", Resource: "controllerrevisions"}
+
+var controllerrevisionsKind = schema.GroupVersionKind{Group: "apps", Version: "v1beta2", Kind: "ControllerRevision"}
+
+// Get takes name of the controllerRevision, and returns the corresponding controllerRevision object, and an error if there is any.
+func (c *FakeControllerRevisions) Get(name string, options v1.GetOptions) (result *v1beta2.ControllerRevision, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(controllerrevisionsResource, c.ns, name), &v1beta2.ControllerRevision{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta2.ControllerRevision), err
+}
+
+// List takes label and field selectors, and returns the list of ControllerRevisions that match those selectors.
+func (c *FakeControllerRevisions) List(opts v1.ListOptions) (result *v1beta2.ControllerRevisionList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(controllerrevisionsResource, controllerrevisionsKind, c.ns, opts), &v1beta2.ControllerRevisionList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta2.ControllerRevisionList{ListMeta: obj.(*v1beta2.ControllerRevisionList).ListMeta}
+ for _, item := range obj.(*v1beta2.ControllerRevisionList).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 controllerRevisions.
+func (c *FakeControllerRevisions) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(controllerrevisionsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a controllerRevision and creates it. Returns the server's representation of the controllerRevision, and an error, if there is any.
+func (c *FakeControllerRevisions) Create(controllerRevision *v1beta2.ControllerRevision) (result *v1beta2.ControllerRevision, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(controllerrevisionsResource, c.ns, controllerRevision), &v1beta2.ControllerRevision{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta2.ControllerRevision), err
+}
+
+// Update takes the representation of a controllerRevision and updates it. Returns the server's representation of the controllerRevision, and an error, if there is any.
+func (c *FakeControllerRevisions) Update(controllerRevision *v1beta2.ControllerRevision) (result *v1beta2.ControllerRevision, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(controllerrevisionsResource, c.ns, controllerRevision), &v1beta2.ControllerRevision{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta2.ControllerRevision), err
+}
+
+// Delete takes name of the controllerRevision and deletes it. Returns an error if one occurs.
+func (c *FakeControllerRevisions) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(controllerrevisionsResource, c.ns, name), &v1beta2.ControllerRevision{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeControllerRevisions) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(controllerrevisionsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta2.ControllerRevisionList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched controllerRevision.
+func (c *FakeControllerRevisions) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta2.ControllerRevision, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(controllerrevisionsResource, c.ns, name, pt, data, subresources...), &v1beta2.ControllerRevision{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta2.ControllerRevision), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_daemonset.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_daemonset.go
new file mode 100644
index 000000000..b50747fdc
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_daemonset.go
@@ -0,0 +1,140 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta2 "k8s.io/api/apps/v1beta2"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeDaemonSets implements DaemonSetInterface
+type FakeDaemonSets struct {
+ Fake *FakeAppsV1beta2
+ ns string
+}
+
+var daemonsetsResource = schema.GroupVersionResource{Group: "apps", Version: "v1beta2", Resource: "daemonsets"}
+
+var daemonsetsKind = schema.GroupVersionKind{Group: "apps", Version: "v1beta2", Kind: "DaemonSet"}
+
+// Get takes name of the daemonSet, and returns the corresponding daemonSet object, and an error if there is any.
+func (c *FakeDaemonSets) Get(name string, options v1.GetOptions) (result *v1beta2.DaemonSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(daemonsetsResource, c.ns, name), &v1beta2.DaemonSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta2.DaemonSet), err
+}
+
+// List takes label and field selectors, and returns the list of DaemonSets that match those selectors.
+func (c *FakeDaemonSets) List(opts v1.ListOptions) (result *v1beta2.DaemonSetList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(daemonsetsResource, daemonsetsKind, c.ns, opts), &v1beta2.DaemonSetList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta2.DaemonSetList{ListMeta: obj.(*v1beta2.DaemonSetList).ListMeta}
+ for _, item := range obj.(*v1beta2.DaemonSetList).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 daemonSets.
+func (c *FakeDaemonSets) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(daemonsetsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a daemonSet and creates it. Returns the server's representation of the daemonSet, and an error, if there is any.
+func (c *FakeDaemonSets) Create(daemonSet *v1beta2.DaemonSet) (result *v1beta2.DaemonSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(daemonsetsResource, c.ns, daemonSet), &v1beta2.DaemonSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta2.DaemonSet), err
+}
+
+// Update takes the representation of a daemonSet and updates it. Returns the server's representation of the daemonSet, and an error, if there is any.
+func (c *FakeDaemonSets) Update(daemonSet *v1beta2.DaemonSet) (result *v1beta2.DaemonSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(daemonsetsResource, c.ns, daemonSet), &v1beta2.DaemonSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta2.DaemonSet), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeDaemonSets) UpdateStatus(daemonSet *v1beta2.DaemonSet) (*v1beta2.DaemonSet, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(daemonsetsResource, "status", c.ns, daemonSet), &v1beta2.DaemonSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta2.DaemonSet), err
+}
+
+// Delete takes name of the daemonSet and deletes it. Returns an error if one occurs.
+func (c *FakeDaemonSets) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(daemonsetsResource, c.ns, name), &v1beta2.DaemonSet{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeDaemonSets) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(daemonsetsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta2.DaemonSetList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched daemonSet.
+func (c *FakeDaemonSets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta2.DaemonSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(daemonsetsResource, c.ns, name, pt, data, subresources...), &v1beta2.DaemonSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta2.DaemonSet), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_deployment.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_deployment.go
new file mode 100644
index 000000000..b74d24ed7
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_deployment.go
@@ -0,0 +1,140 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta2 "k8s.io/api/apps/v1beta2"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeDeployments implements DeploymentInterface
+type FakeDeployments struct {
+ Fake *FakeAppsV1beta2
+ ns string
+}
+
+var deploymentsResource = schema.GroupVersionResource{Group: "apps", Version: "v1beta2", Resource: "deployments"}
+
+var deploymentsKind = schema.GroupVersionKind{Group: "apps", Version: "v1beta2", Kind: "Deployment"}
+
+// Get takes name of the deployment, and returns the corresponding deployment object, and an error if there is any.
+func (c *FakeDeployments) Get(name string, options v1.GetOptions) (result *v1beta2.Deployment, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(deploymentsResource, c.ns, name), &v1beta2.Deployment{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta2.Deployment), err
+}
+
+// List takes label and field selectors, and returns the list of Deployments that match those selectors.
+func (c *FakeDeployments) List(opts v1.ListOptions) (result *v1beta2.DeploymentList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(deploymentsResource, deploymentsKind, c.ns, opts), &v1beta2.DeploymentList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta2.DeploymentList{ListMeta: obj.(*v1beta2.DeploymentList).ListMeta}
+ for _, item := range obj.(*v1beta2.DeploymentList).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 deployments.
+func (c *FakeDeployments) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(deploymentsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a deployment and creates it. Returns the server's representation of the deployment, and an error, if there is any.
+func (c *FakeDeployments) Create(deployment *v1beta2.Deployment) (result *v1beta2.Deployment, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(deploymentsResource, c.ns, deployment), &v1beta2.Deployment{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta2.Deployment), err
+}
+
+// Update takes the representation of a deployment and updates it. Returns the server's representation of the deployment, and an error, if there is any.
+func (c *FakeDeployments) Update(deployment *v1beta2.Deployment) (result *v1beta2.Deployment, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(deploymentsResource, c.ns, deployment), &v1beta2.Deployment{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta2.Deployment), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeDeployments) UpdateStatus(deployment *v1beta2.Deployment) (*v1beta2.Deployment, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(deploymentsResource, "status", c.ns, deployment), &v1beta2.Deployment{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta2.Deployment), err
+}
+
+// Delete takes name of the deployment and deletes it. Returns an error if one occurs.
+func (c *FakeDeployments) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(deploymentsResource, c.ns, name), &v1beta2.Deployment{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeDeployments) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(deploymentsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta2.DeploymentList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched deployment.
+func (c *FakeDeployments) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta2.Deployment, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(deploymentsResource, c.ns, name, pt, data, subresources...), &v1beta2.Deployment{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta2.Deployment), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_replicaset.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_replicaset.go
new file mode 100644
index 000000000..ba1de33ec
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_replicaset.go
@@ -0,0 +1,140 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta2 "k8s.io/api/apps/v1beta2"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeReplicaSets implements ReplicaSetInterface
+type FakeReplicaSets struct {
+ Fake *FakeAppsV1beta2
+ ns string
+}
+
+var replicasetsResource = schema.GroupVersionResource{Group: "apps", Version: "v1beta2", Resource: "replicasets"}
+
+var replicasetsKind = schema.GroupVersionKind{Group: "apps", Version: "v1beta2", Kind: "ReplicaSet"}
+
+// Get takes name of the replicaSet, and returns the corresponding replicaSet object, and an error if there is any.
+func (c *FakeReplicaSets) Get(name string, options v1.GetOptions) (result *v1beta2.ReplicaSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(replicasetsResource, c.ns, name), &v1beta2.ReplicaSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta2.ReplicaSet), err
+}
+
+// List takes label and field selectors, and returns the list of ReplicaSets that match those selectors.
+func (c *FakeReplicaSets) List(opts v1.ListOptions) (result *v1beta2.ReplicaSetList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(replicasetsResource, replicasetsKind, c.ns, opts), &v1beta2.ReplicaSetList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta2.ReplicaSetList{ListMeta: obj.(*v1beta2.ReplicaSetList).ListMeta}
+ for _, item := range obj.(*v1beta2.ReplicaSetList).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 replicaSets.
+func (c *FakeReplicaSets) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(replicasetsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a replicaSet and creates it. Returns the server's representation of the replicaSet, and an error, if there is any.
+func (c *FakeReplicaSets) Create(replicaSet *v1beta2.ReplicaSet) (result *v1beta2.ReplicaSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(replicasetsResource, c.ns, replicaSet), &v1beta2.ReplicaSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta2.ReplicaSet), err
+}
+
+// Update takes the representation of a replicaSet and updates it. Returns the server's representation of the replicaSet, and an error, if there is any.
+func (c *FakeReplicaSets) Update(replicaSet *v1beta2.ReplicaSet) (result *v1beta2.ReplicaSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(replicasetsResource, c.ns, replicaSet), &v1beta2.ReplicaSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta2.ReplicaSet), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeReplicaSets) UpdateStatus(replicaSet *v1beta2.ReplicaSet) (*v1beta2.ReplicaSet, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(replicasetsResource, "status", c.ns, replicaSet), &v1beta2.ReplicaSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta2.ReplicaSet), err
+}
+
+// Delete takes name of the replicaSet and deletes it. Returns an error if one occurs.
+func (c *FakeReplicaSets) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(replicasetsResource, c.ns, name), &v1beta2.ReplicaSet{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeReplicaSets) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(replicasetsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta2.ReplicaSetList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched replicaSet.
+func (c *FakeReplicaSets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta2.ReplicaSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(replicasetsResource, c.ns, name, pt, data, subresources...), &v1beta2.ReplicaSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta2.ReplicaSet), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_statefulset.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_statefulset.go
new file mode 100644
index 000000000..652c7cbc5
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_statefulset.go
@@ -0,0 +1,162 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta2 "k8s.io/api/apps/v1beta2"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeStatefulSets implements StatefulSetInterface
+type FakeStatefulSets struct {
+ Fake *FakeAppsV1beta2
+ ns string
+}
+
+var statefulsetsResource = schema.GroupVersionResource{Group: "apps", Version: "v1beta2", Resource: "statefulsets"}
+
+var statefulsetsKind = schema.GroupVersionKind{Group: "apps", Version: "v1beta2", Kind: "StatefulSet"}
+
+// Get takes name of the statefulSet, and returns the corresponding statefulSet object, and an error if there is any.
+func (c *FakeStatefulSets) Get(name string, options v1.GetOptions) (result *v1beta2.StatefulSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(statefulsetsResource, c.ns, name), &v1beta2.StatefulSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta2.StatefulSet), err
+}
+
+// List takes label and field selectors, and returns the list of StatefulSets that match those selectors.
+func (c *FakeStatefulSets) List(opts v1.ListOptions) (result *v1beta2.StatefulSetList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(statefulsetsResource, statefulsetsKind, c.ns, opts), &v1beta2.StatefulSetList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta2.StatefulSetList{ListMeta: obj.(*v1beta2.StatefulSetList).ListMeta}
+ for _, item := range obj.(*v1beta2.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))
+
+}
+
+// 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 *FakeStatefulSets) Create(statefulSet *v1beta2.StatefulSet) (result *v1beta2.StatefulSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(statefulsetsResource, c.ns, statefulSet), &v1beta2.StatefulSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta2.StatefulSet), err
+}
+
+// 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 *FakeStatefulSets) Update(statefulSet *v1beta2.StatefulSet) (result *v1beta2.StatefulSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(statefulsetsResource, c.ns, statefulSet), &v1beta2.StatefulSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta2.StatefulSet), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeStatefulSets) UpdateStatus(statefulSet *v1beta2.StatefulSet) (*v1beta2.StatefulSet, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(statefulsetsResource, "status", c.ns, statefulSet), &v1beta2.StatefulSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta2.StatefulSet), err
+}
+
+// Delete takes name of the statefulSet and deletes it. Returns an error if one occurs.
+func (c *FakeStatefulSets) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(statefulsetsResource, c.ns, name), &v1beta2.StatefulSet{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeStatefulSets) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(statefulsetsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta2.StatefulSetList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched statefulSet.
+func (c *FakeStatefulSets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta2.StatefulSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(statefulsetsResource, c.ns, name, pt, data, subresources...), &v1beta2.StatefulSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta2.StatefulSet), err
+}
+
+// GetScale takes name of the statefulSet, and returns the corresponding scale object, and an error if there is any.
+func (c *FakeStatefulSets) GetScale(statefulSetName string, options v1.GetOptions) (result *v1beta2.Scale, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetSubresourceAction(statefulsetsResource, c.ns, "scale", statefulSetName), &v1beta2.Scale{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta2.Scale), err
+}
+
+// UpdateScale takes the representation of a scale and updates it. Returns the server's representation of the scale, and an error, if there is any.
+func (c *FakeStatefulSets) UpdateScale(statefulSetName string, scale *v1beta2.Scale) (result *v1beta2.Scale, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(statefulsetsResource, "scale", c.ns, scale), &v1beta2.Scale{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta2.Scale), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/auditregistration/v1alpha1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/auditregistration/v1alpha1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/auditregistration/v1alpha1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/auditregistration/v1alpha1/fake/fake_auditregistration_client.go b/vendor/k8s.io/client-go/kubernetes/typed/auditregistration/v1alpha1/fake/fake_auditregistration_client.go
new file mode 100644
index 000000000..c22acabcf
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/auditregistration/v1alpha1/fake/fake_auditregistration_client.go
@@ -0,0 +1,40 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1alpha1 "k8s.io/client-go/kubernetes/typed/auditregistration/v1alpha1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeAuditregistrationV1alpha1 struct {
+ *testing.Fake
+}
+
+func (c *FakeAuditregistrationV1alpha1) AuditSinks() v1alpha1.AuditSinkInterface {
+ return &FakeAuditSinks{c}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeAuditregistrationV1alpha1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/auditregistration/v1alpha1/fake/fake_auditsink.go b/vendor/k8s.io/client-go/kubernetes/typed/auditregistration/v1alpha1/fake/fake_auditsink.go
new file mode 100644
index 000000000..d0bb9fd00
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/auditregistration/v1alpha1/fake/fake_auditsink.go
@@ -0,0 +1,120 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1alpha1 "k8s.io/api/auditregistration/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeAuditSinks implements AuditSinkInterface
+type FakeAuditSinks struct {
+ Fake *FakeAuditregistrationV1alpha1
+}
+
+var auditsinksResource = schema.GroupVersionResource{Group: "auditregistration.k8s.io", Version: "v1alpha1", Resource: "auditsinks"}
+
+var auditsinksKind = schema.GroupVersionKind{Group: "auditregistration.k8s.io", Version: "v1alpha1", Kind: "AuditSink"}
+
+// Get takes name of the auditSink, and returns the corresponding auditSink object, and an error if there is any.
+func (c *FakeAuditSinks) Get(name string, options v1.GetOptions) (result *v1alpha1.AuditSink, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootGetAction(auditsinksResource, name), &v1alpha1.AuditSink{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.AuditSink), err
+}
+
+// List takes label and field selectors, and returns the list of AuditSinks that match those selectors.
+func (c *FakeAuditSinks) List(opts v1.ListOptions) (result *v1alpha1.AuditSinkList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootListAction(auditsinksResource, auditsinksKind, opts), &v1alpha1.AuditSinkList{})
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1alpha1.AuditSinkList{ListMeta: obj.(*v1alpha1.AuditSinkList).ListMeta}
+ for _, item := range obj.(*v1alpha1.AuditSinkList).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 auditSinks.
+func (c *FakeAuditSinks) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewRootWatchAction(auditsinksResource, opts))
+}
+
+// Create takes the representation of a auditSink and creates it. Returns the server's representation of the auditSink, and an error, if there is any.
+func (c *FakeAuditSinks) Create(auditSink *v1alpha1.AuditSink) (result *v1alpha1.AuditSink, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootCreateAction(auditsinksResource, auditSink), &v1alpha1.AuditSink{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.AuditSink), err
+}
+
+// Update takes the representation of a auditSink and updates it. Returns the server's representation of the auditSink, and an error, if there is any.
+func (c *FakeAuditSinks) Update(auditSink *v1alpha1.AuditSink) (result *v1alpha1.AuditSink, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateAction(auditsinksResource, auditSink), &v1alpha1.AuditSink{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.AuditSink), err
+}
+
+// Delete takes name of the auditSink and deletes it. Returns an error if one occurs.
+func (c *FakeAuditSinks) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewRootDeleteAction(auditsinksResource, name), &v1alpha1.AuditSink{})
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeAuditSinks) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewRootDeleteCollectionAction(auditsinksResource, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1alpha1.AuditSinkList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched auditSink.
+func (c *FakeAuditSinks) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.AuditSink, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootPatchSubresourceAction(auditsinksResource, name, pt, data, subresources...), &v1alpha1.AuditSink{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.AuditSink), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/fake_authentication_client.go b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/fake_authentication_client.go
new file mode 100644
index 000000000..ee06a6cdd
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/fake_authentication_client.go
@@ -0,0 +1,40 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1 "k8s.io/client-go/kubernetes/typed/authentication/v1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeAuthenticationV1 struct {
+ *testing.Fake
+}
+
+func (c *FakeAuthenticationV1) TokenReviews() v1.TokenReviewInterface {
+ return &FakeTokenReviews{c}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeAuthenticationV1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/fake_tokenreview.go b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/fake_tokenreview.go
new file mode 100644
index 000000000..e2a7f72b6
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/fake_tokenreview.go
@@ -0,0 +1,24 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+// FakeTokenReviews implements TokenReviewInterface
+type FakeTokenReviews struct {
+ Fake *FakeAuthenticationV1
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/fake_tokenreview_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/fake_tokenreview_expansion.go
new file mode 100644
index 000000000..7008c927c
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/fake_tokenreview_expansion.go
@@ -0,0 +1,27 @@
+/*
+Copyright 2017 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 (
+ authenticationapi "k8s.io/api/authentication/v1"
+ core "k8s.io/client-go/testing"
+)
+
+func (c *FakeTokenReviews) Create(tokenReview *authenticationapi.TokenReview) (result *authenticationapi.TokenReview, err error) {
+ obj, err := c.Fake.Invokes(core.NewRootCreateAction(authenticationapi.SchemeGroupVersion.WithResource("tokenreviews"), tokenReview), &authenticationapi.TokenReview{})
+ return obj.(*authenticationapi.TokenReview), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/fake_authentication_client.go b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/fake_authentication_client.go
new file mode 100644
index 000000000..7299653ca
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/fake_authentication_client.go
@@ -0,0 +1,40 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/client-go/kubernetes/typed/authentication/v1beta1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeAuthenticationV1beta1 struct {
+ *testing.Fake
+}
+
+func (c *FakeAuthenticationV1beta1) TokenReviews() v1beta1.TokenReviewInterface {
+ return &FakeTokenReviews{c}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeAuthenticationV1beta1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/fake_tokenreview.go b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/fake_tokenreview.go
new file mode 100644
index 000000000..63b6b6a85
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/fake_tokenreview.go
@@ -0,0 +1,24 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+// FakeTokenReviews implements TokenReviewInterface
+type FakeTokenReviews struct {
+ Fake *FakeAuthenticationV1beta1
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/fake_tokenreview_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/fake_tokenreview_expansion.go
new file mode 100644
index 000000000..92ef5d1a1
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/fake_tokenreview_expansion.go
@@ -0,0 +1,27 @@
+/*
+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 (
+ authenticationapi "k8s.io/api/authentication/v1beta1"
+ core "k8s.io/client-go/testing"
+)
+
+func (c *FakeTokenReviews) Create(tokenReview *authenticationapi.TokenReview) (result *authenticationapi.TokenReview, err error) {
+ obj, err := c.Fake.Invokes(core.NewRootCreateAction(authenticationapi.SchemeGroupVersion.WithResource("tokenreviews"), tokenReview), &authenticationapi.TokenReview{})
+ return obj.(*authenticationapi.TokenReview), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_authorization_client.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_authorization_client.go
new file mode 100644
index 000000000..f7e823450
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_authorization_client.go
@@ -0,0 +1,52 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1 "k8s.io/client-go/kubernetes/typed/authorization/v1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeAuthorizationV1 struct {
+ *testing.Fake
+}
+
+func (c *FakeAuthorizationV1) LocalSubjectAccessReviews(namespace string) v1.LocalSubjectAccessReviewInterface {
+ return &FakeLocalSubjectAccessReviews{c, namespace}
+}
+
+func (c *FakeAuthorizationV1) SelfSubjectAccessReviews() v1.SelfSubjectAccessReviewInterface {
+ return &FakeSelfSubjectAccessReviews{c}
+}
+
+func (c *FakeAuthorizationV1) SelfSubjectRulesReviews() v1.SelfSubjectRulesReviewInterface {
+ return &FakeSelfSubjectRulesReviews{c}
+}
+
+func (c *FakeAuthorizationV1) SubjectAccessReviews() v1.SubjectAccessReviewInterface {
+ return &FakeSubjectAccessReviews{c}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeAuthorizationV1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_localsubjectaccessreview.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_localsubjectaccessreview.go
new file mode 100644
index 000000000..778ba9cea
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_localsubjectaccessreview.go
@@ -0,0 +1,25 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+// FakeLocalSubjectAccessReviews implements LocalSubjectAccessReviewInterface
+type FakeLocalSubjectAccessReviews struct {
+ Fake *FakeAuthorizationV1
+ ns string
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_localsubjectaccessreview_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_localsubjectaccessreview_expansion.go
new file mode 100644
index 000000000..a01e415c8
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_localsubjectaccessreview_expansion.go
@@ -0,0 +1,27 @@
+/*
+Copyright 2017 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 (
+ authorizationapi "k8s.io/api/authorization/v1"
+ core "k8s.io/client-go/testing"
+)
+
+func (c *FakeLocalSubjectAccessReviews) Create(sar *authorizationapi.LocalSubjectAccessReview) (result *authorizationapi.LocalSubjectAccessReview, err error) {
+ obj, err := c.Fake.Invokes(core.NewCreateAction(authorizationapi.SchemeGroupVersion.WithResource("localsubjectaccessreviews"), c.ns, sar), &authorizationapi.SubjectAccessReview{})
+ return obj.(*authorizationapi.LocalSubjectAccessReview), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_selfsubjectaccessreview.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_selfsubjectaccessreview.go
new file mode 100644
index 000000000..a43a980ba
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_selfsubjectaccessreview.go
@@ -0,0 +1,24 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+// FakeSelfSubjectAccessReviews implements SelfSubjectAccessReviewInterface
+type FakeSelfSubjectAccessReviews struct {
+ Fake *FakeAuthorizationV1
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_selfsubjectaccessreview_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_selfsubjectaccessreview_expansion.go
new file mode 100644
index 000000000..91acbe029
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_selfsubjectaccessreview_expansion.go
@@ -0,0 +1,27 @@
+/*
+Copyright 2017 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 (
+ authorizationapi "k8s.io/api/authorization/v1"
+ core "k8s.io/client-go/testing"
+)
+
+func (c *FakeSelfSubjectAccessReviews) Create(sar *authorizationapi.SelfSubjectAccessReview) (result *authorizationapi.SelfSubjectAccessReview, err error) {
+ obj, err := c.Fake.Invokes(core.NewRootCreateAction(authorizationapi.SchemeGroupVersion.WithResource("selfsubjectaccessreviews"), sar), &authorizationapi.SelfSubjectAccessReview{})
+ return obj.(*authorizationapi.SelfSubjectAccessReview), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_selfsubjectrulesreview.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_selfsubjectrulesreview.go
new file mode 100644
index 000000000..243f2e89e
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_selfsubjectrulesreview.go
@@ -0,0 +1,24 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+// FakeSelfSubjectRulesReviews implements SelfSubjectRulesReviewInterface
+type FakeSelfSubjectRulesReviews struct {
+ Fake *FakeAuthorizationV1
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_selfsubjectrulesreview_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_selfsubjectrulesreview_expansion.go
new file mode 100644
index 000000000..a6dc95134
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_selfsubjectrulesreview_expansion.go
@@ -0,0 +1,27 @@
+/*
+Copyright 2017 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 (
+ authorizationapi "k8s.io/api/authorization/v1"
+ core "k8s.io/client-go/testing"
+)
+
+func (c *FakeSelfSubjectRulesReviews) Create(srr *authorizationapi.SelfSubjectRulesReview) (result *authorizationapi.SelfSubjectRulesReview, err error) {
+ obj, err := c.Fake.Invokes(core.NewRootCreateAction(authorizationapi.SchemeGroupVersion.WithResource("selfsubjectrulesreviews"), srr), &authorizationapi.SelfSubjectRulesReview{})
+ return obj.(*authorizationapi.SelfSubjectRulesReview), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_subjectaccessreview.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_subjectaccessreview.go
new file mode 100644
index 000000000..d07e56254
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_subjectaccessreview.go
@@ -0,0 +1,24 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+// FakeSubjectAccessReviews implements SubjectAccessReviewInterface
+type FakeSubjectAccessReviews struct {
+ Fake *FakeAuthorizationV1
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_subjectaccessreview_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_subjectaccessreview_expansion.go
new file mode 100644
index 000000000..a2a2f0697
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_subjectaccessreview_expansion.go
@@ -0,0 +1,30 @@
+/*
+Copyright 2017 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 (
+ authorizationapi "k8s.io/api/authorization/v1"
+ core "k8s.io/client-go/testing"
+)
+
+func (c *FakeSubjectAccessReviews) Create(sar *authorizationapi.SubjectAccessReview) (result *authorizationapi.SubjectAccessReview, err error) {
+ obj, err := c.Fake.Invokes(core.NewRootCreateAction(authorizationapi.SchemeGroupVersion.WithResource("subjectaccessreviews"), sar), &authorizationapi.SubjectAccessReview{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*authorizationapi.SubjectAccessReview), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_authorization_client.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_authorization_client.go
new file mode 100644
index 000000000..8e328a57b
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_authorization_client.go
@@ -0,0 +1,52 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/client-go/kubernetes/typed/authorization/v1beta1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeAuthorizationV1beta1 struct {
+ *testing.Fake
+}
+
+func (c *FakeAuthorizationV1beta1) LocalSubjectAccessReviews(namespace string) v1beta1.LocalSubjectAccessReviewInterface {
+ return &FakeLocalSubjectAccessReviews{c, namespace}
+}
+
+func (c *FakeAuthorizationV1beta1) SelfSubjectAccessReviews() v1beta1.SelfSubjectAccessReviewInterface {
+ return &FakeSelfSubjectAccessReviews{c}
+}
+
+func (c *FakeAuthorizationV1beta1) SelfSubjectRulesReviews() v1beta1.SelfSubjectRulesReviewInterface {
+ return &FakeSelfSubjectRulesReviews{c}
+}
+
+func (c *FakeAuthorizationV1beta1) SubjectAccessReviews() v1beta1.SubjectAccessReviewInterface {
+ return &FakeSubjectAccessReviews{c}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeAuthorizationV1beta1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_generated_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_generated_expansion.go
new file mode 100644
index 000000000..8754e39d8
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_generated_expansion.go
@@ -0,0 +1,17 @@
+/*
+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
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_localsubjectaccessreview.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_localsubjectaccessreview.go
new file mode 100644
index 000000000..d02d05e5d
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_localsubjectaccessreview.go
@@ -0,0 +1,25 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+// FakeLocalSubjectAccessReviews implements LocalSubjectAccessReviewInterface
+type FakeLocalSubjectAccessReviews struct {
+ Fake *FakeAuthorizationV1beta1
+ ns string
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_localsubjectaccessreview_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_localsubjectaccessreview_expansion.go
new file mode 100644
index 000000000..5211628f2
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_localsubjectaccessreview_expansion.go
@@ -0,0 +1,27 @@
+/*
+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 (
+ authorizationapi "k8s.io/api/authorization/v1beta1"
+ core "k8s.io/client-go/testing"
+)
+
+func (c *FakeLocalSubjectAccessReviews) Create(sar *authorizationapi.LocalSubjectAccessReview) (result *authorizationapi.LocalSubjectAccessReview, err error) {
+ obj, err := c.Fake.Invokes(core.NewCreateAction(authorizationapi.SchemeGroupVersion.WithResource("localsubjectaccessreviews"), c.ns, sar), &authorizationapi.SubjectAccessReview{})
+ return obj.(*authorizationapi.LocalSubjectAccessReview), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_selfsubjectaccessreview.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_selfsubjectaccessreview.go
new file mode 100644
index 000000000..8f98ce7a3
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_selfsubjectaccessreview.go
@@ -0,0 +1,24 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+// FakeSelfSubjectAccessReviews implements SelfSubjectAccessReviewInterface
+type FakeSelfSubjectAccessReviews struct {
+ Fake *FakeAuthorizationV1beta1
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_selfsubjectaccessreview_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_selfsubjectaccessreview_expansion.go
new file mode 100644
index 000000000..6e3af12a7
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_selfsubjectaccessreview_expansion.go
@@ -0,0 +1,27 @@
+/*
+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 (
+ authorizationapi "k8s.io/api/authorization/v1beta1"
+ core "k8s.io/client-go/testing"
+)
+
+func (c *FakeSelfSubjectAccessReviews) Create(sar *authorizationapi.SelfSubjectAccessReview) (result *authorizationapi.SelfSubjectAccessReview, err error) {
+ obj, err := c.Fake.Invokes(core.NewRootCreateAction(authorizationapi.SchemeGroupVersion.WithResource("selfsubjectaccessreviews"), sar), &authorizationapi.SelfSubjectAccessReview{})
+ return obj.(*authorizationapi.SelfSubjectAccessReview), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_selfsubjectrulesreview.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_selfsubjectrulesreview.go
new file mode 100644
index 000000000..d8466b4c8
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_selfsubjectrulesreview.go
@@ -0,0 +1,24 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+// FakeSelfSubjectRulesReviews implements SelfSubjectRulesReviewInterface
+type FakeSelfSubjectRulesReviews struct {
+ Fake *FakeAuthorizationV1beta1
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_selfsubjectrulesreview_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_selfsubjectrulesreview_expansion.go
new file mode 100644
index 000000000..f92ffd717
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_selfsubjectrulesreview_expansion.go
@@ -0,0 +1,27 @@
+/*
+Copyright 2017 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 (
+ authorizationapi "k8s.io/api/authorization/v1beta1"
+ core "k8s.io/client-go/testing"
+)
+
+func (c *FakeSelfSubjectRulesReviews) Create(srr *authorizationapi.SelfSubjectRulesReview) (result *authorizationapi.SelfSubjectRulesReview, err error) {
+ obj, err := c.Fake.Invokes(core.NewRootCreateAction(authorizationapi.SchemeGroupVersion.WithResource("selfsubjectrulesreviews"), srr), &authorizationapi.SelfSubjectRulesReview{})
+ return obj.(*authorizationapi.SelfSubjectRulesReview), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_subjectaccessreview.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_subjectaccessreview.go
new file mode 100644
index 000000000..0d0abdb72
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_subjectaccessreview.go
@@ -0,0 +1,24 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+// FakeSubjectAccessReviews implements SubjectAccessReviewInterface
+type FakeSubjectAccessReviews struct {
+ Fake *FakeAuthorizationV1beta1
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_subjectaccessreview_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_subjectaccessreview_expansion.go
new file mode 100644
index 000000000..b0b18b099
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_subjectaccessreview_expansion.go
@@ -0,0 +1,27 @@
+/*
+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 (
+ authorizationapi "k8s.io/api/authorization/v1beta1"
+ core "k8s.io/client-go/testing"
+)
+
+func (c *FakeSubjectAccessReviews) Create(sar *authorizationapi.SubjectAccessReview) (result *authorizationapi.SubjectAccessReview, err error) {
+ obj, err := c.Fake.Invokes(core.NewRootCreateAction(authorizationapi.SchemeGroupVersion.WithResource("subjectaccessreviews"), sar), &authorizationapi.SubjectAccessReview{})
+ return obj.(*authorizationapi.SubjectAccessReview), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/fake_autoscaling_client.go b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/fake_autoscaling_client.go
new file mode 100644
index 000000000..99e26fcf3
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/fake_autoscaling_client.go
@@ -0,0 +1,40 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1 "k8s.io/client-go/kubernetes/typed/autoscaling/v1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeAutoscalingV1 struct {
+ *testing.Fake
+}
+
+func (c *FakeAutoscalingV1) HorizontalPodAutoscalers(namespace string) v1.HorizontalPodAutoscalerInterface {
+ return &FakeHorizontalPodAutoscalers{c, namespace}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeAutoscalingV1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/fake_horizontalpodautoscaler.go b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/fake_horizontalpodautoscaler.go
new file mode 100644
index 000000000..6a4bf9881
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/fake_horizontalpodautoscaler.go
@@ -0,0 +1,140 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ autoscalingv1 "k8s.io/api/autoscaling/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeHorizontalPodAutoscalers implements HorizontalPodAutoscalerInterface
+type FakeHorizontalPodAutoscalers struct {
+ Fake *FakeAutoscalingV1
+ ns string
+}
+
+var horizontalpodautoscalersResource = schema.GroupVersionResource{Group: "autoscaling", Version: "v1", Resource: "horizontalpodautoscalers"}
+
+var horizontalpodautoscalersKind = schema.GroupVersionKind{Group: "autoscaling", Version: "v1", Kind: "HorizontalPodAutoscaler"}
+
+// Get takes name of the horizontalPodAutoscaler, and returns the corresponding horizontalPodAutoscaler object, and an error if there is any.
+func (c *FakeHorizontalPodAutoscalers) Get(name string, options v1.GetOptions) (result *autoscalingv1.HorizontalPodAutoscaler, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(horizontalpodautoscalersResource, c.ns, name), &autoscalingv1.HorizontalPodAutoscaler{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*autoscalingv1.HorizontalPodAutoscaler), err
+}
+
+// List takes label and field selectors, and returns the list of HorizontalPodAutoscalers that match those selectors.
+func (c *FakeHorizontalPodAutoscalers) List(opts v1.ListOptions) (result *autoscalingv1.HorizontalPodAutoscalerList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(horizontalpodautoscalersResource, horizontalpodautoscalersKind, c.ns, opts), &autoscalingv1.HorizontalPodAutoscalerList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &autoscalingv1.HorizontalPodAutoscalerList{ListMeta: obj.(*autoscalingv1.HorizontalPodAutoscalerList).ListMeta}
+ for _, item := range obj.(*autoscalingv1.HorizontalPodAutoscalerList).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 horizontalPodAutoscalers.
+func (c *FakeHorizontalPodAutoscalers) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(horizontalpodautoscalersResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a horizontalPodAutoscaler and creates it. Returns the server's representation of the horizontalPodAutoscaler, and an error, if there is any.
+func (c *FakeHorizontalPodAutoscalers) Create(horizontalPodAutoscaler *autoscalingv1.HorizontalPodAutoscaler) (result *autoscalingv1.HorizontalPodAutoscaler, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(horizontalpodautoscalersResource, c.ns, horizontalPodAutoscaler), &autoscalingv1.HorizontalPodAutoscaler{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*autoscalingv1.HorizontalPodAutoscaler), err
+}
+
+// Update takes the representation of a horizontalPodAutoscaler and updates it. Returns the server's representation of the horizontalPodAutoscaler, and an error, if there is any.
+func (c *FakeHorizontalPodAutoscalers) Update(horizontalPodAutoscaler *autoscalingv1.HorizontalPodAutoscaler) (result *autoscalingv1.HorizontalPodAutoscaler, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(horizontalpodautoscalersResource, c.ns, horizontalPodAutoscaler), &autoscalingv1.HorizontalPodAutoscaler{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*autoscalingv1.HorizontalPodAutoscaler), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeHorizontalPodAutoscalers) UpdateStatus(horizontalPodAutoscaler *autoscalingv1.HorizontalPodAutoscaler) (*autoscalingv1.HorizontalPodAutoscaler, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(horizontalpodautoscalersResource, "status", c.ns, horizontalPodAutoscaler), &autoscalingv1.HorizontalPodAutoscaler{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*autoscalingv1.HorizontalPodAutoscaler), err
+}
+
+// Delete takes name of the horizontalPodAutoscaler and deletes it. Returns an error if one occurs.
+func (c *FakeHorizontalPodAutoscalers) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(horizontalpodautoscalersResource, c.ns, name), &autoscalingv1.HorizontalPodAutoscaler{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeHorizontalPodAutoscalers) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(horizontalpodautoscalersResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &autoscalingv1.HorizontalPodAutoscalerList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched horizontalPodAutoscaler.
+func (c *FakeHorizontalPodAutoscalers) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *autoscalingv1.HorizontalPodAutoscaler, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(horizontalpodautoscalersResource, c.ns, name, pt, data, subresources...), &autoscalingv1.HorizontalPodAutoscaler{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*autoscalingv1.HorizontalPodAutoscaler), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/fake_autoscaling_client.go b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/fake_autoscaling_client.go
new file mode 100644
index 000000000..be8e0f48e
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/fake_autoscaling_client.go
@@ -0,0 +1,40 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v2beta1 "k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeAutoscalingV2beta1 struct {
+ *testing.Fake
+}
+
+func (c *FakeAutoscalingV2beta1) HorizontalPodAutoscalers(namespace string) v2beta1.HorizontalPodAutoscalerInterface {
+ return &FakeHorizontalPodAutoscalers{c, namespace}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeAutoscalingV2beta1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/fake_horizontalpodautoscaler.go b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/fake_horizontalpodautoscaler.go
new file mode 100644
index 000000000..514a787cb
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/fake_horizontalpodautoscaler.go
@@ -0,0 +1,140 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v2beta1 "k8s.io/api/autoscaling/v2beta1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeHorizontalPodAutoscalers implements HorizontalPodAutoscalerInterface
+type FakeHorizontalPodAutoscalers struct {
+ Fake *FakeAutoscalingV2beta1
+ ns string
+}
+
+var horizontalpodautoscalersResource = schema.GroupVersionResource{Group: "autoscaling", Version: "v2beta1", Resource: "horizontalpodautoscalers"}
+
+var horizontalpodautoscalersKind = schema.GroupVersionKind{Group: "autoscaling", Version: "v2beta1", Kind: "HorizontalPodAutoscaler"}
+
+// Get takes name of the horizontalPodAutoscaler, and returns the corresponding horizontalPodAutoscaler object, and an error if there is any.
+func (c *FakeHorizontalPodAutoscalers) Get(name string, options v1.GetOptions) (result *v2beta1.HorizontalPodAutoscaler, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(horizontalpodautoscalersResource, c.ns, name), &v2beta1.HorizontalPodAutoscaler{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v2beta1.HorizontalPodAutoscaler), err
+}
+
+// List takes label and field selectors, and returns the list of HorizontalPodAutoscalers that match those selectors.
+func (c *FakeHorizontalPodAutoscalers) List(opts v1.ListOptions) (result *v2beta1.HorizontalPodAutoscalerList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(horizontalpodautoscalersResource, horizontalpodautoscalersKind, c.ns, opts), &v2beta1.HorizontalPodAutoscalerList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v2beta1.HorizontalPodAutoscalerList{ListMeta: obj.(*v2beta1.HorizontalPodAutoscalerList).ListMeta}
+ for _, item := range obj.(*v2beta1.HorizontalPodAutoscalerList).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 horizontalPodAutoscalers.
+func (c *FakeHorizontalPodAutoscalers) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(horizontalpodautoscalersResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a horizontalPodAutoscaler and creates it. Returns the server's representation of the horizontalPodAutoscaler, and an error, if there is any.
+func (c *FakeHorizontalPodAutoscalers) Create(horizontalPodAutoscaler *v2beta1.HorizontalPodAutoscaler) (result *v2beta1.HorizontalPodAutoscaler, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(horizontalpodautoscalersResource, c.ns, horizontalPodAutoscaler), &v2beta1.HorizontalPodAutoscaler{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v2beta1.HorizontalPodAutoscaler), err
+}
+
+// Update takes the representation of a horizontalPodAutoscaler and updates it. Returns the server's representation of the horizontalPodAutoscaler, and an error, if there is any.
+func (c *FakeHorizontalPodAutoscalers) Update(horizontalPodAutoscaler *v2beta1.HorizontalPodAutoscaler) (result *v2beta1.HorizontalPodAutoscaler, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(horizontalpodautoscalersResource, c.ns, horizontalPodAutoscaler), &v2beta1.HorizontalPodAutoscaler{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v2beta1.HorizontalPodAutoscaler), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeHorizontalPodAutoscalers) UpdateStatus(horizontalPodAutoscaler *v2beta1.HorizontalPodAutoscaler) (*v2beta1.HorizontalPodAutoscaler, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(horizontalpodautoscalersResource, "status", c.ns, horizontalPodAutoscaler), &v2beta1.HorizontalPodAutoscaler{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v2beta1.HorizontalPodAutoscaler), err
+}
+
+// Delete takes name of the horizontalPodAutoscaler and deletes it. Returns an error if one occurs.
+func (c *FakeHorizontalPodAutoscalers) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(horizontalpodautoscalersResource, c.ns, name), &v2beta1.HorizontalPodAutoscaler{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeHorizontalPodAutoscalers) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(horizontalpodautoscalersResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v2beta1.HorizontalPodAutoscalerList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched horizontalPodAutoscaler.
+func (c *FakeHorizontalPodAutoscalers) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v2beta1.HorizontalPodAutoscaler, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(horizontalpodautoscalersResource, c.ns, name, pt, data, subresources...), &v2beta1.HorizontalPodAutoscaler{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v2beta1.HorizontalPodAutoscaler), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta2/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta2/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta2/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta2/fake/fake_autoscaling_client.go b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta2/fake/fake_autoscaling_client.go
new file mode 100644
index 000000000..8c36e0e81
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta2/fake/fake_autoscaling_client.go
@@ -0,0 +1,40 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v2beta2 "k8s.io/client-go/kubernetes/typed/autoscaling/v2beta2"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeAutoscalingV2beta2 struct {
+ *testing.Fake
+}
+
+func (c *FakeAutoscalingV2beta2) HorizontalPodAutoscalers(namespace string) v2beta2.HorizontalPodAutoscalerInterface {
+ return &FakeHorizontalPodAutoscalers{c, namespace}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeAutoscalingV2beta2) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta2/fake/fake_horizontalpodautoscaler.go b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta2/fake/fake_horizontalpodautoscaler.go
new file mode 100644
index 000000000..c0569f00a
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta2/fake/fake_horizontalpodautoscaler.go
@@ -0,0 +1,140 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v2beta2 "k8s.io/api/autoscaling/v2beta2"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeHorizontalPodAutoscalers implements HorizontalPodAutoscalerInterface
+type FakeHorizontalPodAutoscalers struct {
+ Fake *FakeAutoscalingV2beta2
+ ns string
+}
+
+var horizontalpodautoscalersResource = schema.GroupVersionResource{Group: "autoscaling", Version: "v2beta2", Resource: "horizontalpodautoscalers"}
+
+var horizontalpodautoscalersKind = schema.GroupVersionKind{Group: "autoscaling", Version: "v2beta2", Kind: "HorizontalPodAutoscaler"}
+
+// Get takes name of the horizontalPodAutoscaler, and returns the corresponding horizontalPodAutoscaler object, and an error if there is any.
+func (c *FakeHorizontalPodAutoscalers) Get(name string, options v1.GetOptions) (result *v2beta2.HorizontalPodAutoscaler, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(horizontalpodautoscalersResource, c.ns, name), &v2beta2.HorizontalPodAutoscaler{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v2beta2.HorizontalPodAutoscaler), err
+}
+
+// List takes label and field selectors, and returns the list of HorizontalPodAutoscalers that match those selectors.
+func (c *FakeHorizontalPodAutoscalers) List(opts v1.ListOptions) (result *v2beta2.HorizontalPodAutoscalerList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(horizontalpodautoscalersResource, horizontalpodautoscalersKind, c.ns, opts), &v2beta2.HorizontalPodAutoscalerList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v2beta2.HorizontalPodAutoscalerList{ListMeta: obj.(*v2beta2.HorizontalPodAutoscalerList).ListMeta}
+ for _, item := range obj.(*v2beta2.HorizontalPodAutoscalerList).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 horizontalPodAutoscalers.
+func (c *FakeHorizontalPodAutoscalers) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(horizontalpodautoscalersResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a horizontalPodAutoscaler and creates it. Returns the server's representation of the horizontalPodAutoscaler, and an error, if there is any.
+func (c *FakeHorizontalPodAutoscalers) Create(horizontalPodAutoscaler *v2beta2.HorizontalPodAutoscaler) (result *v2beta2.HorizontalPodAutoscaler, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(horizontalpodautoscalersResource, c.ns, horizontalPodAutoscaler), &v2beta2.HorizontalPodAutoscaler{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v2beta2.HorizontalPodAutoscaler), err
+}
+
+// Update takes the representation of a horizontalPodAutoscaler and updates it. Returns the server's representation of the horizontalPodAutoscaler, and an error, if there is any.
+func (c *FakeHorizontalPodAutoscalers) Update(horizontalPodAutoscaler *v2beta2.HorizontalPodAutoscaler) (result *v2beta2.HorizontalPodAutoscaler, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(horizontalpodautoscalersResource, c.ns, horizontalPodAutoscaler), &v2beta2.HorizontalPodAutoscaler{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v2beta2.HorizontalPodAutoscaler), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeHorizontalPodAutoscalers) UpdateStatus(horizontalPodAutoscaler *v2beta2.HorizontalPodAutoscaler) (*v2beta2.HorizontalPodAutoscaler, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(horizontalpodautoscalersResource, "status", c.ns, horizontalPodAutoscaler), &v2beta2.HorizontalPodAutoscaler{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v2beta2.HorizontalPodAutoscaler), err
+}
+
+// Delete takes name of the horizontalPodAutoscaler and deletes it. Returns an error if one occurs.
+func (c *FakeHorizontalPodAutoscalers) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(horizontalpodautoscalersResource, c.ns, name), &v2beta2.HorizontalPodAutoscaler{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeHorizontalPodAutoscalers) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(horizontalpodautoscalersResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v2beta2.HorizontalPodAutoscalerList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched horizontalPodAutoscaler.
+func (c *FakeHorizontalPodAutoscalers) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v2beta2.HorizontalPodAutoscaler, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(horizontalpodautoscalersResource, c.ns, name, pt, data, subresources...), &v2beta2.HorizontalPodAutoscaler{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v2beta2.HorizontalPodAutoscaler), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/fake/fake_batch_client.go b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/fake/fake_batch_client.go
new file mode 100644
index 000000000..c90dd7561
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/fake/fake_batch_client.go
@@ -0,0 +1,40 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1 "k8s.io/client-go/kubernetes/typed/batch/v1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeBatchV1 struct {
+ *testing.Fake
+}
+
+func (c *FakeBatchV1) Jobs(namespace string) v1.JobInterface {
+ return &FakeJobs{c, namespace}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeBatchV1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/fake/fake_job.go b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/fake/fake_job.go
new file mode 100644
index 000000000..06dc25c6b
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/fake/fake_job.go
@@ -0,0 +1,140 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ batchv1 "k8s.io/api/batch/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeJobs implements JobInterface
+type FakeJobs struct {
+ Fake *FakeBatchV1
+ ns string
+}
+
+var jobsResource = schema.GroupVersionResource{Group: "batch", Version: "v1", Resource: "jobs"}
+
+var jobsKind = schema.GroupVersionKind{Group: "batch", Version: "v1", Kind: "Job"}
+
+// Get takes name of the job, and returns the corresponding job object, and an error if there is any.
+func (c *FakeJobs) Get(name string, options v1.GetOptions) (result *batchv1.Job, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(jobsResource, c.ns, name), &batchv1.Job{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*batchv1.Job), err
+}
+
+// List takes label and field selectors, and returns the list of Jobs that match those selectors.
+func (c *FakeJobs) List(opts v1.ListOptions) (result *batchv1.JobList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(jobsResource, jobsKind, c.ns, opts), &batchv1.JobList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &batchv1.JobList{ListMeta: obj.(*batchv1.JobList).ListMeta}
+ for _, item := range obj.(*batchv1.JobList).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 jobs.
+func (c *FakeJobs) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(jobsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a job and creates it. Returns the server's representation of the job, and an error, if there is any.
+func (c *FakeJobs) Create(job *batchv1.Job) (result *batchv1.Job, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(jobsResource, c.ns, job), &batchv1.Job{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*batchv1.Job), err
+}
+
+// Update takes the representation of a job and updates it. Returns the server's representation of the job, and an error, if there is any.
+func (c *FakeJobs) Update(job *batchv1.Job) (result *batchv1.Job, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(jobsResource, c.ns, job), &batchv1.Job{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*batchv1.Job), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeJobs) UpdateStatus(job *batchv1.Job) (*batchv1.Job, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(jobsResource, "status", c.ns, job), &batchv1.Job{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*batchv1.Job), err
+}
+
+// Delete takes name of the job and deletes it. Returns an error if one occurs.
+func (c *FakeJobs) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(jobsResource, c.ns, name), &batchv1.Job{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeJobs) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(jobsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &batchv1.JobList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched job.
+func (c *FakeJobs) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *batchv1.Job, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(jobsResource, c.ns, name, pt, data, subresources...), &batchv1.Job{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*batchv1.Job), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/fake_batch_client.go b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/fake_batch_client.go
new file mode 100644
index 000000000..6f350aed9
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/fake_batch_client.go
@@ -0,0 +1,40 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/client-go/kubernetes/typed/batch/v1beta1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeBatchV1beta1 struct {
+ *testing.Fake
+}
+
+func (c *FakeBatchV1beta1) CronJobs(namespace string) v1beta1.CronJobInterface {
+ return &FakeCronJobs{c, namespace}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeBatchV1beta1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/fake_cronjob.go b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/fake_cronjob.go
new file mode 100644
index 000000000..3985c4037
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/fake_cronjob.go
@@ -0,0 +1,140 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/api/batch/v1beta1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeCronJobs implements CronJobInterface
+type FakeCronJobs struct {
+ Fake *FakeBatchV1beta1
+ ns string
+}
+
+var cronjobsResource = schema.GroupVersionResource{Group: "batch", Version: "v1beta1", Resource: "cronjobs"}
+
+var cronjobsKind = schema.GroupVersionKind{Group: "batch", Version: "v1beta1", Kind: "CronJob"}
+
+// Get takes name of the cronJob, and returns the corresponding cronJob object, and an error if there is any.
+func (c *FakeCronJobs) Get(name string, options v1.GetOptions) (result *v1beta1.CronJob, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(cronjobsResource, c.ns, name), &v1beta1.CronJob{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.CronJob), err
+}
+
+// List takes label and field selectors, and returns the list of CronJobs that match those selectors.
+func (c *FakeCronJobs) List(opts v1.ListOptions) (result *v1beta1.CronJobList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(cronjobsResource, cronjobsKind, c.ns, opts), &v1beta1.CronJobList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta1.CronJobList{ListMeta: obj.(*v1beta1.CronJobList).ListMeta}
+ for _, item := range obj.(*v1beta1.CronJobList).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 cronJobs.
+func (c *FakeCronJobs) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(cronjobsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a cronJob and creates it. Returns the server's representation of the cronJob, and an error, if there is any.
+func (c *FakeCronJobs) Create(cronJob *v1beta1.CronJob) (result *v1beta1.CronJob, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(cronjobsResource, c.ns, cronJob), &v1beta1.CronJob{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.CronJob), err
+}
+
+// Update takes the representation of a cronJob and updates it. Returns the server's representation of the cronJob, and an error, if there is any.
+func (c *FakeCronJobs) Update(cronJob *v1beta1.CronJob) (result *v1beta1.CronJob, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(cronjobsResource, c.ns, cronJob), &v1beta1.CronJob{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.CronJob), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeCronJobs) UpdateStatus(cronJob *v1beta1.CronJob) (*v1beta1.CronJob, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(cronjobsResource, "status", c.ns, cronJob), &v1beta1.CronJob{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.CronJob), err
+}
+
+// Delete takes name of the cronJob and deletes it. Returns an error if one occurs.
+func (c *FakeCronJobs) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(cronjobsResource, c.ns, name), &v1beta1.CronJob{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeCronJobs) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(cronjobsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta1.CronJobList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched cronJob.
+func (c *FakeCronJobs) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.CronJob, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(cronjobsResource, c.ns, name, pt, data, subresources...), &v1beta1.CronJob{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.CronJob), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/fake_batch_client.go b/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/fake_batch_client.go
new file mode 100644
index 000000000..3e478cde9
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/fake_batch_client.go
@@ -0,0 +1,40 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v2alpha1 "k8s.io/client-go/kubernetes/typed/batch/v2alpha1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeBatchV2alpha1 struct {
+ *testing.Fake
+}
+
+func (c *FakeBatchV2alpha1) CronJobs(namespace string) v2alpha1.CronJobInterface {
+ return &FakeCronJobs{c, namespace}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeBatchV2alpha1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/fake_cronjob.go b/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/fake_cronjob.go
new file mode 100644
index 000000000..2195027d2
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/fake_cronjob.go
@@ -0,0 +1,140 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v2alpha1 "k8s.io/api/batch/v2alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeCronJobs implements CronJobInterface
+type FakeCronJobs struct {
+ Fake *FakeBatchV2alpha1
+ ns string
+}
+
+var cronjobsResource = schema.GroupVersionResource{Group: "batch", Version: "v2alpha1", Resource: "cronjobs"}
+
+var cronjobsKind = schema.GroupVersionKind{Group: "batch", Version: "v2alpha1", Kind: "CronJob"}
+
+// Get takes name of the cronJob, and returns the corresponding cronJob object, and an error if there is any.
+func (c *FakeCronJobs) Get(name string, options v1.GetOptions) (result *v2alpha1.CronJob, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(cronjobsResource, c.ns, name), &v2alpha1.CronJob{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v2alpha1.CronJob), err
+}
+
+// List takes label and field selectors, and returns the list of CronJobs that match those selectors.
+func (c *FakeCronJobs) List(opts v1.ListOptions) (result *v2alpha1.CronJobList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(cronjobsResource, cronjobsKind, c.ns, opts), &v2alpha1.CronJobList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v2alpha1.CronJobList{ListMeta: obj.(*v2alpha1.CronJobList).ListMeta}
+ for _, item := range obj.(*v2alpha1.CronJobList).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 cronJobs.
+func (c *FakeCronJobs) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(cronjobsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a cronJob and creates it. Returns the server's representation of the cronJob, and an error, if there is any.
+func (c *FakeCronJobs) Create(cronJob *v2alpha1.CronJob) (result *v2alpha1.CronJob, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(cronjobsResource, c.ns, cronJob), &v2alpha1.CronJob{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v2alpha1.CronJob), err
+}
+
+// Update takes the representation of a cronJob and updates it. Returns the server's representation of the cronJob, and an error, if there is any.
+func (c *FakeCronJobs) Update(cronJob *v2alpha1.CronJob) (result *v2alpha1.CronJob, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(cronjobsResource, c.ns, cronJob), &v2alpha1.CronJob{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v2alpha1.CronJob), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeCronJobs) UpdateStatus(cronJob *v2alpha1.CronJob) (*v2alpha1.CronJob, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(cronjobsResource, "status", c.ns, cronJob), &v2alpha1.CronJob{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v2alpha1.CronJob), err
+}
+
+// Delete takes name of the cronJob and deletes it. Returns an error if one occurs.
+func (c *FakeCronJobs) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(cronjobsResource, c.ns, name), &v2alpha1.CronJob{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeCronJobs) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(cronjobsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v2alpha1.CronJobList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched cronJob.
+func (c *FakeCronJobs) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v2alpha1.CronJob, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(cronjobsResource, c.ns, name, pt, data, subresources...), &v2alpha1.CronJob{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v2alpha1.CronJob), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/fake_certificates_client.go b/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/fake_certificates_client.go
new file mode 100644
index 000000000..29d8b088e
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/fake_certificates_client.go
@@ -0,0 +1,40 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/client-go/kubernetes/typed/certificates/v1beta1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeCertificatesV1beta1 struct {
+ *testing.Fake
+}
+
+func (c *FakeCertificatesV1beta1) CertificateSigningRequests() v1beta1.CertificateSigningRequestInterface {
+ return &FakeCertificateSigningRequests{c}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeCertificatesV1beta1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/fake_certificatesigningrequest.go b/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/fake_certificatesigningrequest.go
new file mode 100644
index 000000000..aa45c8803
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/fake_certificatesigningrequest.go
@@ -0,0 +1,131 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/api/certificates/v1beta1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeCertificateSigningRequests implements CertificateSigningRequestInterface
+type FakeCertificateSigningRequests struct {
+ Fake *FakeCertificatesV1beta1
+}
+
+var certificatesigningrequestsResource = schema.GroupVersionResource{Group: "certificates.k8s.io", Version: "v1beta1", Resource: "certificatesigningrequests"}
+
+var certificatesigningrequestsKind = schema.GroupVersionKind{Group: "certificates.k8s.io", Version: "v1beta1", Kind: "CertificateSigningRequest"}
+
+// Get takes name of the certificateSigningRequest, and returns the corresponding certificateSigningRequest object, and an error if there is any.
+func (c *FakeCertificateSigningRequests) Get(name string, options v1.GetOptions) (result *v1beta1.CertificateSigningRequest, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootGetAction(certificatesigningrequestsResource, name), &v1beta1.CertificateSigningRequest{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.CertificateSigningRequest), err
+}
+
+// List takes label and field selectors, and returns the list of CertificateSigningRequests that match those selectors.
+func (c *FakeCertificateSigningRequests) List(opts v1.ListOptions) (result *v1beta1.CertificateSigningRequestList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootListAction(certificatesigningrequestsResource, certificatesigningrequestsKind, opts), &v1beta1.CertificateSigningRequestList{})
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta1.CertificateSigningRequestList{ListMeta: obj.(*v1beta1.CertificateSigningRequestList).ListMeta}
+ for _, item := range obj.(*v1beta1.CertificateSigningRequestList).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 certificateSigningRequests.
+func (c *FakeCertificateSigningRequests) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewRootWatchAction(certificatesigningrequestsResource, opts))
+}
+
+// Create takes the representation of a certificateSigningRequest and creates it. Returns the server's representation of the certificateSigningRequest, and an error, if there is any.
+func (c *FakeCertificateSigningRequests) Create(certificateSigningRequest *v1beta1.CertificateSigningRequest) (result *v1beta1.CertificateSigningRequest, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootCreateAction(certificatesigningrequestsResource, certificateSigningRequest), &v1beta1.CertificateSigningRequest{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.CertificateSigningRequest), err
+}
+
+// Update takes the representation of a certificateSigningRequest and updates it. Returns the server's representation of the certificateSigningRequest, and an error, if there is any.
+func (c *FakeCertificateSigningRequests) Update(certificateSigningRequest *v1beta1.CertificateSigningRequest) (result *v1beta1.CertificateSigningRequest, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateAction(certificatesigningrequestsResource, certificateSigningRequest), &v1beta1.CertificateSigningRequest{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.CertificateSigningRequest), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeCertificateSigningRequests) UpdateStatus(certificateSigningRequest *v1beta1.CertificateSigningRequest) (*v1beta1.CertificateSigningRequest, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateSubresourceAction(certificatesigningrequestsResource, "status", certificateSigningRequest), &v1beta1.CertificateSigningRequest{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.CertificateSigningRequest), err
+}
+
+// Delete takes name of the certificateSigningRequest and deletes it. Returns an error if one occurs.
+func (c *FakeCertificateSigningRequests) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewRootDeleteAction(certificatesigningrequestsResource, name), &v1beta1.CertificateSigningRequest{})
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeCertificateSigningRequests) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewRootDeleteCollectionAction(certificatesigningrequestsResource, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta1.CertificateSigningRequestList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched certificateSigningRequest.
+func (c *FakeCertificateSigningRequests) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.CertificateSigningRequest, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootPatchSubresourceAction(certificatesigningrequestsResource, name, pt, data, subresources...), &v1beta1.CertificateSigningRequest{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.CertificateSigningRequest), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/fake_certificatesigningrequest_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/fake_certificatesigningrequest_expansion.go
new file mode 100644
index 000000000..8af33e62a
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/fake_certificatesigningrequest_expansion.go
@@ -0,0 +1,31 @@
+/*
+Copyright 2017 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 (
+ certificates "k8s.io/api/certificates/v1beta1"
+ core "k8s.io/client-go/testing"
+)
+
+func (c *FakeCertificateSigningRequests) UpdateApproval(certificateSigningRequest *certificates.CertificateSigningRequest) (result *certificates.CertificateSigningRequest, err error) {
+ obj, err := c.Fake.
+ Invokes(core.NewRootUpdateSubresourceAction(certificatesigningrequestsResource, "approval", certificateSigningRequest), &certificates.CertificateSigningRequest{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*certificates.CertificateSigningRequest), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/coordination/v1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/coordination/v1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/coordination/v1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/coordination/v1/fake/fake_coordination_client.go b/vendor/k8s.io/client-go/kubernetes/typed/coordination/v1/fake/fake_coordination_client.go
new file mode 100644
index 000000000..6920275b2
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/coordination/v1/fake/fake_coordination_client.go
@@ -0,0 +1,40 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1 "k8s.io/client-go/kubernetes/typed/coordination/v1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeCoordinationV1 struct {
+ *testing.Fake
+}
+
+func (c *FakeCoordinationV1) Leases(namespace string) v1.LeaseInterface {
+ return &FakeLeases{c, namespace}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeCoordinationV1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/coordination/v1/fake/fake_lease.go b/vendor/k8s.io/client-go/kubernetes/typed/coordination/v1/fake/fake_lease.go
new file mode 100644
index 000000000..940c738c1
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/coordination/v1/fake/fake_lease.go
@@ -0,0 +1,128 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ coordinationv1 "k8s.io/api/coordination/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeLeases implements LeaseInterface
+type FakeLeases struct {
+ Fake *FakeCoordinationV1
+ ns string
+}
+
+var leasesResource = schema.GroupVersionResource{Group: "coordination.k8s.io", Version: "v1", Resource: "leases"}
+
+var leasesKind = schema.GroupVersionKind{Group: "coordination.k8s.io", Version: "v1", Kind: "Lease"}
+
+// Get takes name of the lease, and returns the corresponding lease object, and an error if there is any.
+func (c *FakeLeases) Get(name string, options v1.GetOptions) (result *coordinationv1.Lease, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(leasesResource, c.ns, name), &coordinationv1.Lease{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*coordinationv1.Lease), err
+}
+
+// List takes label and field selectors, and returns the list of Leases that match those selectors.
+func (c *FakeLeases) List(opts v1.ListOptions) (result *coordinationv1.LeaseList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(leasesResource, leasesKind, c.ns, opts), &coordinationv1.LeaseList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &coordinationv1.LeaseList{ListMeta: obj.(*coordinationv1.LeaseList).ListMeta}
+ for _, item := range obj.(*coordinationv1.LeaseList).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 leases.
+func (c *FakeLeases) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(leasesResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a lease and creates it. Returns the server's representation of the lease, and an error, if there is any.
+func (c *FakeLeases) Create(lease *coordinationv1.Lease) (result *coordinationv1.Lease, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(leasesResource, c.ns, lease), &coordinationv1.Lease{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*coordinationv1.Lease), err
+}
+
+// Update takes the representation of a lease and updates it. Returns the server's representation of the lease, and an error, if there is any.
+func (c *FakeLeases) Update(lease *coordinationv1.Lease) (result *coordinationv1.Lease, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(leasesResource, c.ns, lease), &coordinationv1.Lease{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*coordinationv1.Lease), err
+}
+
+// Delete takes name of the lease and deletes it. Returns an error if one occurs.
+func (c *FakeLeases) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(leasesResource, c.ns, name), &coordinationv1.Lease{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeLeases) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(leasesResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &coordinationv1.LeaseList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched lease.
+func (c *FakeLeases) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *coordinationv1.Lease, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(leasesResource, c.ns, name, pt, data, subresources...), &coordinationv1.Lease{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*coordinationv1.Lease), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/coordination/v1beta1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/coordination/v1beta1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/coordination/v1beta1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/coordination/v1beta1/fake/fake_coordination_client.go b/vendor/k8s.io/client-go/kubernetes/typed/coordination/v1beta1/fake/fake_coordination_client.go
new file mode 100644
index 000000000..f583b466e
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/coordination/v1beta1/fake/fake_coordination_client.go
@@ -0,0 +1,40 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/client-go/kubernetes/typed/coordination/v1beta1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeCoordinationV1beta1 struct {
+ *testing.Fake
+}
+
+func (c *FakeCoordinationV1beta1) Leases(namespace string) v1beta1.LeaseInterface {
+ return &FakeLeases{c, namespace}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeCoordinationV1beta1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/coordination/v1beta1/fake/fake_lease.go b/vendor/k8s.io/client-go/kubernetes/typed/coordination/v1beta1/fake/fake_lease.go
new file mode 100644
index 000000000..0ebf3bffc
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/coordination/v1beta1/fake/fake_lease.go
@@ -0,0 +1,128 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/api/coordination/v1beta1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeLeases implements LeaseInterface
+type FakeLeases struct {
+ Fake *FakeCoordinationV1beta1
+ ns string
+}
+
+var leasesResource = schema.GroupVersionResource{Group: "coordination.k8s.io", Version: "v1beta1", Resource: "leases"}
+
+var leasesKind = schema.GroupVersionKind{Group: "coordination.k8s.io", Version: "v1beta1", Kind: "Lease"}
+
+// Get takes name of the lease, and returns the corresponding lease object, and an error if there is any.
+func (c *FakeLeases) Get(name string, options v1.GetOptions) (result *v1beta1.Lease, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(leasesResource, c.ns, name), &v1beta1.Lease{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Lease), err
+}
+
+// List takes label and field selectors, and returns the list of Leases that match those selectors.
+func (c *FakeLeases) List(opts v1.ListOptions) (result *v1beta1.LeaseList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(leasesResource, leasesKind, c.ns, opts), &v1beta1.LeaseList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta1.LeaseList{ListMeta: obj.(*v1beta1.LeaseList).ListMeta}
+ for _, item := range obj.(*v1beta1.LeaseList).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 leases.
+func (c *FakeLeases) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(leasesResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a lease and creates it. Returns the server's representation of the lease, and an error, if there is any.
+func (c *FakeLeases) Create(lease *v1beta1.Lease) (result *v1beta1.Lease, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(leasesResource, c.ns, lease), &v1beta1.Lease{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Lease), err
+}
+
+// Update takes the representation of a lease and updates it. Returns the server's representation of the lease, and an error, if there is any.
+func (c *FakeLeases) Update(lease *v1beta1.Lease) (result *v1beta1.Lease, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(leasesResource, c.ns, lease), &v1beta1.Lease{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Lease), err
+}
+
+// Delete takes name of the lease and deletes it. Returns an error if one occurs.
+func (c *FakeLeases) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(leasesResource, c.ns, name), &v1beta1.Lease{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeLeases) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(leasesResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta1.LeaseList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched lease.
+func (c *FakeLeases) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.Lease, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(leasesResource, c.ns, name, pt, data, subresources...), &v1beta1.Lease{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Lease), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_componentstatus.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_componentstatus.go
new file mode 100644
index 000000000..18beedc2d
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_componentstatus.go
@@ -0,0 +1,120 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ corev1 "k8s.io/api/core/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeComponentStatuses implements ComponentStatusInterface
+type FakeComponentStatuses struct {
+ Fake *FakeCoreV1
+}
+
+var componentstatusesResource = schema.GroupVersionResource{Group: "", Version: "v1", Resource: "componentstatuses"}
+
+var componentstatusesKind = schema.GroupVersionKind{Group: "", Version: "v1", Kind: "ComponentStatus"}
+
+// Get takes name of the componentStatus, and returns the corresponding componentStatus object, and an error if there is any.
+func (c *FakeComponentStatuses) Get(name string, options v1.GetOptions) (result *corev1.ComponentStatus, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootGetAction(componentstatusesResource, name), &corev1.ComponentStatus{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.ComponentStatus), err
+}
+
+// List takes label and field selectors, and returns the list of ComponentStatuses that match those selectors.
+func (c *FakeComponentStatuses) List(opts v1.ListOptions) (result *corev1.ComponentStatusList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootListAction(componentstatusesResource, componentstatusesKind, opts), &corev1.ComponentStatusList{})
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &corev1.ComponentStatusList{ListMeta: obj.(*corev1.ComponentStatusList).ListMeta}
+ for _, item := range obj.(*corev1.ComponentStatusList).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 componentStatuses.
+func (c *FakeComponentStatuses) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewRootWatchAction(componentstatusesResource, opts))
+}
+
+// Create takes the representation of a componentStatus and creates it. Returns the server's representation of the componentStatus, and an error, if there is any.
+func (c *FakeComponentStatuses) Create(componentStatus *corev1.ComponentStatus) (result *corev1.ComponentStatus, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootCreateAction(componentstatusesResource, componentStatus), &corev1.ComponentStatus{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.ComponentStatus), err
+}
+
+// Update takes the representation of a componentStatus and updates it. Returns the server's representation of the componentStatus, and an error, if there is any.
+func (c *FakeComponentStatuses) Update(componentStatus *corev1.ComponentStatus) (result *corev1.ComponentStatus, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateAction(componentstatusesResource, componentStatus), &corev1.ComponentStatus{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.ComponentStatus), err
+}
+
+// Delete takes name of the componentStatus and deletes it. Returns an error if one occurs.
+func (c *FakeComponentStatuses) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewRootDeleteAction(componentstatusesResource, name), &corev1.ComponentStatus{})
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeComponentStatuses) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewRootDeleteCollectionAction(componentstatusesResource, listOptions)
+
+ _, err := c.Fake.Invokes(action, &corev1.ComponentStatusList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched componentStatus.
+func (c *FakeComponentStatuses) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.ComponentStatus, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootPatchSubresourceAction(componentstatusesResource, name, pt, data, subresources...), &corev1.ComponentStatus{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.ComponentStatus), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_configmap.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_configmap.go
new file mode 100644
index 000000000..2361ac3fe
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_configmap.go
@@ -0,0 +1,128 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ corev1 "k8s.io/api/core/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeConfigMaps implements ConfigMapInterface
+type FakeConfigMaps struct {
+ Fake *FakeCoreV1
+ ns string
+}
+
+var configmapsResource = schema.GroupVersionResource{Group: "", Version: "v1", Resource: "configmaps"}
+
+var configmapsKind = schema.GroupVersionKind{Group: "", Version: "v1", Kind: "ConfigMap"}
+
+// Get takes name of the configMap, and returns the corresponding configMap object, and an error if there is any.
+func (c *FakeConfigMaps) Get(name string, options v1.GetOptions) (result *corev1.ConfigMap, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(configmapsResource, c.ns, name), &corev1.ConfigMap{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.ConfigMap), err
+}
+
+// List takes label and field selectors, and returns the list of ConfigMaps that match those selectors.
+func (c *FakeConfigMaps) List(opts v1.ListOptions) (result *corev1.ConfigMapList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(configmapsResource, configmapsKind, c.ns, opts), &corev1.ConfigMapList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &corev1.ConfigMapList{ListMeta: obj.(*corev1.ConfigMapList).ListMeta}
+ for _, item := range obj.(*corev1.ConfigMapList).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 configMaps.
+func (c *FakeConfigMaps) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(configmapsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a configMap and creates it. Returns the server's representation of the configMap, and an error, if there is any.
+func (c *FakeConfigMaps) Create(configMap *corev1.ConfigMap) (result *corev1.ConfigMap, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(configmapsResource, c.ns, configMap), &corev1.ConfigMap{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.ConfigMap), err
+}
+
+// Update takes the representation of a configMap and updates it. Returns the server's representation of the configMap, and an error, if there is any.
+func (c *FakeConfigMaps) Update(configMap *corev1.ConfigMap) (result *corev1.ConfigMap, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(configmapsResource, c.ns, configMap), &corev1.ConfigMap{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.ConfigMap), err
+}
+
+// Delete takes name of the configMap and deletes it. Returns an error if one occurs.
+func (c *FakeConfigMaps) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(configmapsResource, c.ns, name), &corev1.ConfigMap{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeConfigMaps) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(configmapsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &corev1.ConfigMapList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched configMap.
+func (c *FakeConfigMaps) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.ConfigMap, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(configmapsResource, c.ns, name, pt, data, subresources...), &corev1.ConfigMap{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.ConfigMap), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_core_client.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_core_client.go
new file mode 100644
index 000000000..5ad90943c
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_core_client.go
@@ -0,0 +1,100 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1 "k8s.io/client-go/kubernetes/typed/core/v1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeCoreV1 struct {
+ *testing.Fake
+}
+
+func (c *FakeCoreV1) ComponentStatuses() v1.ComponentStatusInterface {
+ return &FakeComponentStatuses{c}
+}
+
+func (c *FakeCoreV1) ConfigMaps(namespace string) v1.ConfigMapInterface {
+ return &FakeConfigMaps{c, namespace}
+}
+
+func (c *FakeCoreV1) Endpoints(namespace string) v1.EndpointsInterface {
+ return &FakeEndpoints{c, namespace}
+}
+
+func (c *FakeCoreV1) Events(namespace string) v1.EventInterface {
+ return &FakeEvents{c, namespace}
+}
+
+func (c *FakeCoreV1) LimitRanges(namespace string) v1.LimitRangeInterface {
+ return &FakeLimitRanges{c, namespace}
+}
+
+func (c *FakeCoreV1) Namespaces() v1.NamespaceInterface {
+ return &FakeNamespaces{c}
+}
+
+func (c *FakeCoreV1) Nodes() v1.NodeInterface {
+ return &FakeNodes{c}
+}
+
+func (c *FakeCoreV1) PersistentVolumes() v1.PersistentVolumeInterface {
+ return &FakePersistentVolumes{c}
+}
+
+func (c *FakeCoreV1) PersistentVolumeClaims(namespace string) v1.PersistentVolumeClaimInterface {
+ return &FakePersistentVolumeClaims{c, namespace}
+}
+
+func (c *FakeCoreV1) Pods(namespace string) v1.PodInterface {
+ return &FakePods{c, namespace}
+}
+
+func (c *FakeCoreV1) PodTemplates(namespace string) v1.PodTemplateInterface {
+ return &FakePodTemplates{c, namespace}
+}
+
+func (c *FakeCoreV1) ReplicationControllers(namespace string) v1.ReplicationControllerInterface {
+ return &FakeReplicationControllers{c, namespace}
+}
+
+func (c *FakeCoreV1) ResourceQuotas(namespace string) v1.ResourceQuotaInterface {
+ return &FakeResourceQuotas{c, namespace}
+}
+
+func (c *FakeCoreV1) Secrets(namespace string) v1.SecretInterface {
+ return &FakeSecrets{c, namespace}
+}
+
+func (c *FakeCoreV1) Services(namespace string) v1.ServiceInterface {
+ return &FakeServices{c, namespace}
+}
+
+func (c *FakeCoreV1) ServiceAccounts(namespace string) v1.ServiceAccountInterface {
+ return &FakeServiceAccounts{c, namespace}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeCoreV1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_endpoints.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_endpoints.go
new file mode 100644
index 000000000..d521af408
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_endpoints.go
@@ -0,0 +1,128 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ corev1 "k8s.io/api/core/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeEndpoints implements EndpointsInterface
+type FakeEndpoints struct {
+ Fake *FakeCoreV1
+ ns string
+}
+
+var endpointsResource = schema.GroupVersionResource{Group: "", Version: "v1", Resource: "endpoints"}
+
+var endpointsKind = schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Endpoints"}
+
+// Get takes name of the endpoints, and returns the corresponding endpoints object, and an error if there is any.
+func (c *FakeEndpoints) Get(name string, options v1.GetOptions) (result *corev1.Endpoints, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(endpointsResource, c.ns, name), &corev1.Endpoints{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Endpoints), err
+}
+
+// List takes label and field selectors, and returns the list of Endpoints that match those selectors.
+func (c *FakeEndpoints) List(opts v1.ListOptions) (result *corev1.EndpointsList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(endpointsResource, endpointsKind, c.ns, opts), &corev1.EndpointsList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &corev1.EndpointsList{ListMeta: obj.(*corev1.EndpointsList).ListMeta}
+ for _, item := range obj.(*corev1.EndpointsList).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 endpoints.
+func (c *FakeEndpoints) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(endpointsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a endpoints and creates it. Returns the server's representation of the endpoints, and an error, if there is any.
+func (c *FakeEndpoints) Create(endpoints *corev1.Endpoints) (result *corev1.Endpoints, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(endpointsResource, c.ns, endpoints), &corev1.Endpoints{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Endpoints), err
+}
+
+// Update takes the representation of a endpoints and updates it. Returns the server's representation of the endpoints, and an error, if there is any.
+func (c *FakeEndpoints) Update(endpoints *corev1.Endpoints) (result *corev1.Endpoints, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(endpointsResource, c.ns, endpoints), &corev1.Endpoints{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Endpoints), err
+}
+
+// Delete takes name of the endpoints and deletes it. Returns an error if one occurs.
+func (c *FakeEndpoints) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(endpointsResource, c.ns, name), &corev1.Endpoints{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeEndpoints) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(endpointsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &corev1.EndpointsList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched endpoints.
+func (c *FakeEndpoints) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.Endpoints, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(endpointsResource, c.ns, name, pt, data, subresources...), &corev1.Endpoints{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Endpoints), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_event.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_event.go
new file mode 100644
index 000000000..3444f4be9
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_event.go
@@ -0,0 +1,128 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ corev1 "k8s.io/api/core/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeEvents implements EventInterface
+type FakeEvents struct {
+ Fake *FakeCoreV1
+ ns string
+}
+
+var eventsResource = schema.GroupVersionResource{Group: "", Version: "v1", Resource: "events"}
+
+var eventsKind = schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Event"}
+
+// Get takes name of the event, and returns the corresponding event object, and an error if there is any.
+func (c *FakeEvents) Get(name string, options v1.GetOptions) (result *corev1.Event, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(eventsResource, c.ns, name), &corev1.Event{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Event), err
+}
+
+// List takes label and field selectors, and returns the list of Events that match those selectors.
+func (c *FakeEvents) List(opts v1.ListOptions) (result *corev1.EventList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(eventsResource, eventsKind, c.ns, opts), &corev1.EventList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &corev1.EventList{ListMeta: obj.(*corev1.EventList).ListMeta}
+ for _, item := range obj.(*corev1.EventList).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 events.
+func (c *FakeEvents) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(eventsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a event and creates it. Returns the server's representation of the event, and an error, if there is any.
+func (c *FakeEvents) Create(event *corev1.Event) (result *corev1.Event, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(eventsResource, c.ns, event), &corev1.Event{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Event), err
+}
+
+// Update takes the representation of a event and updates it. Returns the server's representation of the event, and an error, if there is any.
+func (c *FakeEvents) Update(event *corev1.Event) (result *corev1.Event, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(eventsResource, c.ns, event), &corev1.Event{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Event), err
+}
+
+// Delete takes name of the event and deletes it. Returns an error if one occurs.
+func (c *FakeEvents) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(eventsResource, c.ns, name), &corev1.Event{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeEvents) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(eventsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &corev1.EventList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched event.
+func (c *FakeEvents) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.Event, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(eventsResource, c.ns, name, pt, data, subresources...), &corev1.Event{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Event), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_event_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_event_expansion.go
new file mode 100644
index 000000000..4b4c90d7d
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_event_expansion.go
@@ -0,0 +1,93 @@
+/*
+Copyright 2014 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 (
+ "k8s.io/api/core/v1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/fields"
+ "k8s.io/apimachinery/pkg/runtime"
+ types "k8s.io/apimachinery/pkg/types"
+ core "k8s.io/client-go/testing"
+)
+
+func (c *FakeEvents) CreateWithEventNamespace(event *v1.Event) (*v1.Event, error) {
+ action := core.NewRootCreateAction(eventsResource, event)
+ if c.ns != "" {
+ action = core.NewCreateAction(eventsResource, c.ns, event)
+ }
+ obj, err := c.Fake.Invokes(action, event)
+ if obj == nil {
+ return nil, err
+ }
+
+ return obj.(*v1.Event), err
+}
+
+// Update replaces an existing event. Returns the copy of the event the server returns, or an error.
+func (c *FakeEvents) UpdateWithEventNamespace(event *v1.Event) (*v1.Event, error) {
+ action := core.NewRootUpdateAction(eventsResource, event)
+ if c.ns != "" {
+ action = core.NewUpdateAction(eventsResource, c.ns, event)
+ }
+ obj, err := c.Fake.Invokes(action, event)
+ if obj == nil {
+ return nil, err
+ }
+
+ return obj.(*v1.Event), err
+}
+
+// PatchWithEventNamespace patches an existing event. Returns the copy of the event the server returns, or an error.
+// TODO: Should take a PatchType as an argument probably.
+func (c *FakeEvents) PatchWithEventNamespace(event *v1.Event, data []byte) (*v1.Event, error) {
+ // TODO: Should be configurable to support additional patch strategies.
+ pt := types.StrategicMergePatchType
+ action := core.NewRootPatchAction(eventsResource, event.Name, pt, data)
+ if c.ns != "" {
+ action = core.NewPatchAction(eventsResource, c.ns, event.Name, pt, data)
+ }
+ obj, err := c.Fake.Invokes(action, event)
+ if obj == nil {
+ return nil, err
+ }
+
+ return obj.(*v1.Event), err
+}
+
+// Search returns a list of events matching the specified object.
+func (c *FakeEvents) Search(scheme *runtime.Scheme, objOrRef runtime.Object) (*v1.EventList, error) {
+ action := core.NewRootListAction(eventsResource, eventsKind, metav1.ListOptions{})
+ if c.ns != "" {
+ action = core.NewListAction(eventsResource, eventsKind, c.ns, metav1.ListOptions{})
+ }
+ obj, err := c.Fake.Invokes(action, &v1.EventList{})
+ if obj == nil {
+ return nil, err
+ }
+
+ return obj.(*v1.EventList), err
+}
+
+func (c *FakeEvents) GetFieldSelector(involvedObjectName, involvedObjectNamespace, involvedObjectKind, involvedObjectUID *string) fields.Selector {
+ action := core.GenericActionImpl{}
+ action.Verb = "get-field-selector"
+ action.Resource = eventsResource
+
+ c.Fake.Invokes(action, nil)
+ return fields.Everything()
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_limitrange.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_limitrange.go
new file mode 100644
index 000000000..d110031f8
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_limitrange.go
@@ -0,0 +1,128 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ corev1 "k8s.io/api/core/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeLimitRanges implements LimitRangeInterface
+type FakeLimitRanges struct {
+ Fake *FakeCoreV1
+ ns string
+}
+
+var limitrangesResource = schema.GroupVersionResource{Group: "", Version: "v1", Resource: "limitranges"}
+
+var limitrangesKind = schema.GroupVersionKind{Group: "", Version: "v1", Kind: "LimitRange"}
+
+// Get takes name of the limitRange, and returns the corresponding limitRange object, and an error if there is any.
+func (c *FakeLimitRanges) Get(name string, options v1.GetOptions) (result *corev1.LimitRange, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(limitrangesResource, c.ns, name), &corev1.LimitRange{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.LimitRange), err
+}
+
+// List takes label and field selectors, and returns the list of LimitRanges that match those selectors.
+func (c *FakeLimitRanges) List(opts v1.ListOptions) (result *corev1.LimitRangeList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(limitrangesResource, limitrangesKind, c.ns, opts), &corev1.LimitRangeList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &corev1.LimitRangeList{ListMeta: obj.(*corev1.LimitRangeList).ListMeta}
+ for _, item := range obj.(*corev1.LimitRangeList).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 limitRanges.
+func (c *FakeLimitRanges) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(limitrangesResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a limitRange and creates it. Returns the server's representation of the limitRange, and an error, if there is any.
+func (c *FakeLimitRanges) Create(limitRange *corev1.LimitRange) (result *corev1.LimitRange, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(limitrangesResource, c.ns, limitRange), &corev1.LimitRange{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.LimitRange), err
+}
+
+// Update takes the representation of a limitRange and updates it. Returns the server's representation of the limitRange, and an error, if there is any.
+func (c *FakeLimitRanges) Update(limitRange *corev1.LimitRange) (result *corev1.LimitRange, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(limitrangesResource, c.ns, limitRange), &corev1.LimitRange{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.LimitRange), err
+}
+
+// Delete takes name of the limitRange and deletes it. Returns an error if one occurs.
+func (c *FakeLimitRanges) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(limitrangesResource, c.ns, name), &corev1.LimitRange{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeLimitRanges) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(limitrangesResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &corev1.LimitRangeList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched limitRange.
+func (c *FakeLimitRanges) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.LimitRange, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(limitrangesResource, c.ns, name, pt, data, subresources...), &corev1.LimitRange{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.LimitRange), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_namespace.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_namespace.go
new file mode 100644
index 000000000..21387b5e2
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_namespace.go
@@ -0,0 +1,123 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ corev1 "k8s.io/api/core/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeNamespaces implements NamespaceInterface
+type FakeNamespaces struct {
+ Fake *FakeCoreV1
+}
+
+var namespacesResource = schema.GroupVersionResource{Group: "", Version: "v1", Resource: "namespaces"}
+
+var namespacesKind = schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Namespace"}
+
+// Get takes name of the namespace, and returns the corresponding namespace object, and an error if there is any.
+func (c *FakeNamespaces) Get(name string, options v1.GetOptions) (result *corev1.Namespace, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootGetAction(namespacesResource, name), &corev1.Namespace{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Namespace), err
+}
+
+// List takes label and field selectors, and returns the list of Namespaces that match those selectors.
+func (c *FakeNamespaces) List(opts v1.ListOptions) (result *corev1.NamespaceList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootListAction(namespacesResource, namespacesKind, opts), &corev1.NamespaceList{})
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &corev1.NamespaceList{ListMeta: obj.(*corev1.NamespaceList).ListMeta}
+ for _, item := range obj.(*corev1.NamespaceList).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 namespaces.
+func (c *FakeNamespaces) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewRootWatchAction(namespacesResource, opts))
+}
+
+// Create takes the representation of a namespace and creates it. Returns the server's representation of the namespace, and an error, if there is any.
+func (c *FakeNamespaces) Create(namespace *corev1.Namespace) (result *corev1.Namespace, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootCreateAction(namespacesResource, namespace), &corev1.Namespace{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Namespace), err
+}
+
+// Update takes the representation of a namespace and updates it. Returns the server's representation of the namespace, and an error, if there is any.
+func (c *FakeNamespaces) Update(namespace *corev1.Namespace) (result *corev1.Namespace, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateAction(namespacesResource, namespace), &corev1.Namespace{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Namespace), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeNamespaces) UpdateStatus(namespace *corev1.Namespace) (*corev1.Namespace, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateSubresourceAction(namespacesResource, "status", namespace), &corev1.Namespace{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Namespace), err
+}
+
+// Delete takes name of the namespace and deletes it. Returns an error if one occurs.
+func (c *FakeNamespaces) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewRootDeleteAction(namespacesResource, name), &corev1.Namespace{})
+ return err
+}
+
+// Patch applies the patch and returns the patched namespace.
+func (c *FakeNamespaces) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.Namespace, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootPatchSubresourceAction(namespacesResource, name, pt, data, subresources...), &corev1.Namespace{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Namespace), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_namespace_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_namespace_expansion.go
new file mode 100644
index 000000000..a0eae3490
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_namespace_expansion.go
@@ -0,0 +1,37 @@
+/*
+Copyright 2014 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 (
+ "k8s.io/api/core/v1"
+ core "k8s.io/client-go/testing"
+)
+
+func (c *FakeNamespaces) Finalize(namespace *v1.Namespace) (*v1.Namespace, error) {
+ action := core.CreateActionImpl{}
+ action.Verb = "create"
+ action.Resource = namespacesResource
+ action.Subresource = "finalize"
+ action.Object = namespace
+
+ obj, err := c.Fake.Invokes(action, namespace)
+ if obj == nil {
+ return nil, err
+ }
+
+ return obj.(*v1.Namespace), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_node.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_node.go
new file mode 100644
index 000000000..bcde116a4
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_node.go
@@ -0,0 +1,131 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ corev1 "k8s.io/api/core/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeNodes implements NodeInterface
+type FakeNodes struct {
+ Fake *FakeCoreV1
+}
+
+var nodesResource = schema.GroupVersionResource{Group: "", Version: "v1", Resource: "nodes"}
+
+var nodesKind = schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Node"}
+
+// Get takes name of the node, and returns the corresponding node object, and an error if there is any.
+func (c *FakeNodes) Get(name string, options v1.GetOptions) (result *corev1.Node, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootGetAction(nodesResource, name), &corev1.Node{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Node), err
+}
+
+// List takes label and field selectors, and returns the list of Nodes that match those selectors.
+func (c *FakeNodes) List(opts v1.ListOptions) (result *corev1.NodeList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootListAction(nodesResource, nodesKind, opts), &corev1.NodeList{})
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &corev1.NodeList{ListMeta: obj.(*corev1.NodeList).ListMeta}
+ for _, item := range obj.(*corev1.NodeList).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 nodes.
+func (c *FakeNodes) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewRootWatchAction(nodesResource, opts))
+}
+
+// Create takes the representation of a node and creates it. Returns the server's representation of the node, and an error, if there is any.
+func (c *FakeNodes) Create(node *corev1.Node) (result *corev1.Node, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootCreateAction(nodesResource, node), &corev1.Node{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Node), err
+}
+
+// Update takes the representation of a node and updates it. Returns the server's representation of the node, and an error, if there is any.
+func (c *FakeNodes) Update(node *corev1.Node) (result *corev1.Node, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateAction(nodesResource, node), &corev1.Node{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Node), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeNodes) UpdateStatus(node *corev1.Node) (*corev1.Node, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateSubresourceAction(nodesResource, "status", node), &corev1.Node{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Node), err
+}
+
+// Delete takes name of the node and deletes it. Returns an error if one occurs.
+func (c *FakeNodes) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewRootDeleteAction(nodesResource, name), &corev1.Node{})
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeNodes) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewRootDeleteCollectionAction(nodesResource, listOptions)
+
+ _, err := c.Fake.Invokes(action, &corev1.NodeList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched node.
+func (c *FakeNodes) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.Node, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootPatchSubresourceAction(nodesResource, name, pt, data, subresources...), &corev1.Node{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Node), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_node_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_node_expansion.go
new file mode 100644
index 000000000..a39022c83
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_node_expansion.go
@@ -0,0 +1,36 @@
+/*
+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 (
+ "k8s.io/api/core/v1"
+ types "k8s.io/apimachinery/pkg/types"
+ core "k8s.io/client-go/testing"
+)
+
+// TODO: Should take a PatchType as an argument probably.
+func (c *FakeNodes) PatchStatus(nodeName string, data []byte) (*v1.Node, error) {
+ // TODO: Should be configurable to support additional patch strategies.
+ pt := types.StrategicMergePatchType
+ obj, err := c.Fake.Invokes(
+ core.NewRootPatchSubresourceAction(nodesResource, nodeName, pt, data, "status"), &v1.Node{})
+ if obj == nil {
+ return nil, err
+ }
+
+ return obj.(*v1.Node), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_persistentvolume.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_persistentvolume.go
new file mode 100644
index 000000000..843f32307
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_persistentvolume.go
@@ -0,0 +1,131 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ corev1 "k8s.io/api/core/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakePersistentVolumes implements PersistentVolumeInterface
+type FakePersistentVolumes struct {
+ Fake *FakeCoreV1
+}
+
+var persistentvolumesResource = schema.GroupVersionResource{Group: "", Version: "v1", Resource: "persistentvolumes"}
+
+var persistentvolumesKind = schema.GroupVersionKind{Group: "", Version: "v1", Kind: "PersistentVolume"}
+
+// Get takes name of the persistentVolume, and returns the corresponding persistentVolume object, and an error if there is any.
+func (c *FakePersistentVolumes) Get(name string, options v1.GetOptions) (result *corev1.PersistentVolume, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootGetAction(persistentvolumesResource, name), &corev1.PersistentVolume{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.PersistentVolume), err
+}
+
+// List takes label and field selectors, and returns the list of PersistentVolumes that match those selectors.
+func (c *FakePersistentVolumes) List(opts v1.ListOptions) (result *corev1.PersistentVolumeList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootListAction(persistentvolumesResource, persistentvolumesKind, opts), &corev1.PersistentVolumeList{})
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &corev1.PersistentVolumeList{ListMeta: obj.(*corev1.PersistentVolumeList).ListMeta}
+ for _, item := range obj.(*corev1.PersistentVolumeList).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 persistentVolumes.
+func (c *FakePersistentVolumes) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewRootWatchAction(persistentvolumesResource, opts))
+}
+
+// Create takes the representation of a persistentVolume and creates it. Returns the server's representation of the persistentVolume, and an error, if there is any.
+func (c *FakePersistentVolumes) Create(persistentVolume *corev1.PersistentVolume) (result *corev1.PersistentVolume, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootCreateAction(persistentvolumesResource, persistentVolume), &corev1.PersistentVolume{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.PersistentVolume), err
+}
+
+// Update takes the representation of a persistentVolume and updates it. Returns the server's representation of the persistentVolume, and an error, if there is any.
+func (c *FakePersistentVolumes) Update(persistentVolume *corev1.PersistentVolume) (result *corev1.PersistentVolume, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateAction(persistentvolumesResource, persistentVolume), &corev1.PersistentVolume{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.PersistentVolume), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakePersistentVolumes) UpdateStatus(persistentVolume *corev1.PersistentVolume) (*corev1.PersistentVolume, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateSubresourceAction(persistentvolumesResource, "status", persistentVolume), &corev1.PersistentVolume{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.PersistentVolume), err
+}
+
+// Delete takes name of the persistentVolume and deletes it. Returns an error if one occurs.
+func (c *FakePersistentVolumes) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewRootDeleteAction(persistentvolumesResource, name), &corev1.PersistentVolume{})
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakePersistentVolumes) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewRootDeleteCollectionAction(persistentvolumesResource, listOptions)
+
+ _, err := c.Fake.Invokes(action, &corev1.PersistentVolumeList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched persistentVolume.
+func (c *FakePersistentVolumes) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.PersistentVolume, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootPatchSubresourceAction(persistentvolumesResource, name, pt, data, subresources...), &corev1.PersistentVolume{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.PersistentVolume), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_persistentvolumeclaim.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_persistentvolumeclaim.go
new file mode 100644
index 000000000..d2557c4c8
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_persistentvolumeclaim.go
@@ -0,0 +1,140 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ corev1 "k8s.io/api/core/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakePersistentVolumeClaims implements PersistentVolumeClaimInterface
+type FakePersistentVolumeClaims struct {
+ Fake *FakeCoreV1
+ ns string
+}
+
+var persistentvolumeclaimsResource = schema.GroupVersionResource{Group: "", Version: "v1", Resource: "persistentvolumeclaims"}
+
+var persistentvolumeclaimsKind = schema.GroupVersionKind{Group: "", Version: "v1", Kind: "PersistentVolumeClaim"}
+
+// Get takes name of the persistentVolumeClaim, and returns the corresponding persistentVolumeClaim object, and an error if there is any.
+func (c *FakePersistentVolumeClaims) Get(name string, options v1.GetOptions) (result *corev1.PersistentVolumeClaim, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(persistentvolumeclaimsResource, c.ns, name), &corev1.PersistentVolumeClaim{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.PersistentVolumeClaim), err
+}
+
+// List takes label and field selectors, and returns the list of PersistentVolumeClaims that match those selectors.
+func (c *FakePersistentVolumeClaims) List(opts v1.ListOptions) (result *corev1.PersistentVolumeClaimList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(persistentvolumeclaimsResource, persistentvolumeclaimsKind, c.ns, opts), &corev1.PersistentVolumeClaimList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &corev1.PersistentVolumeClaimList{ListMeta: obj.(*corev1.PersistentVolumeClaimList).ListMeta}
+ for _, item := range obj.(*corev1.PersistentVolumeClaimList).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 persistentVolumeClaims.
+func (c *FakePersistentVolumeClaims) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(persistentvolumeclaimsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a persistentVolumeClaim and creates it. Returns the server's representation of the persistentVolumeClaim, and an error, if there is any.
+func (c *FakePersistentVolumeClaims) Create(persistentVolumeClaim *corev1.PersistentVolumeClaim) (result *corev1.PersistentVolumeClaim, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(persistentvolumeclaimsResource, c.ns, persistentVolumeClaim), &corev1.PersistentVolumeClaim{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.PersistentVolumeClaim), err
+}
+
+// Update takes the representation of a persistentVolumeClaim and updates it. Returns the server's representation of the persistentVolumeClaim, and an error, if there is any.
+func (c *FakePersistentVolumeClaims) Update(persistentVolumeClaim *corev1.PersistentVolumeClaim) (result *corev1.PersistentVolumeClaim, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(persistentvolumeclaimsResource, c.ns, persistentVolumeClaim), &corev1.PersistentVolumeClaim{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.PersistentVolumeClaim), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakePersistentVolumeClaims) UpdateStatus(persistentVolumeClaim *corev1.PersistentVolumeClaim) (*corev1.PersistentVolumeClaim, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(persistentvolumeclaimsResource, "status", c.ns, persistentVolumeClaim), &corev1.PersistentVolumeClaim{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.PersistentVolumeClaim), err
+}
+
+// Delete takes name of the persistentVolumeClaim and deletes it. Returns an error if one occurs.
+func (c *FakePersistentVolumeClaims) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(persistentvolumeclaimsResource, c.ns, name), &corev1.PersistentVolumeClaim{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakePersistentVolumeClaims) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(persistentvolumeclaimsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &corev1.PersistentVolumeClaimList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched persistentVolumeClaim.
+func (c *FakePersistentVolumeClaims) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.PersistentVolumeClaim, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(persistentvolumeclaimsResource, c.ns, name, pt, data, subresources...), &corev1.PersistentVolumeClaim{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.PersistentVolumeClaim), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_pod.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_pod.go
new file mode 100644
index 000000000..2dbecbbaa
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_pod.go
@@ -0,0 +1,140 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ corev1 "k8s.io/api/core/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakePods implements PodInterface
+type FakePods struct {
+ Fake *FakeCoreV1
+ ns string
+}
+
+var podsResource = schema.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}
+
+var podsKind = schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"}
+
+// Get takes name of the pod, and returns the corresponding pod object, and an error if there is any.
+func (c *FakePods) Get(name string, options v1.GetOptions) (result *corev1.Pod, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(podsResource, c.ns, name), &corev1.Pod{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Pod), err
+}
+
+// List takes label and field selectors, and returns the list of Pods that match those selectors.
+func (c *FakePods) List(opts v1.ListOptions) (result *corev1.PodList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(podsResource, podsKind, c.ns, opts), &corev1.PodList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &corev1.PodList{ListMeta: obj.(*corev1.PodList).ListMeta}
+ for _, item := range obj.(*corev1.PodList).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 pods.
+func (c *FakePods) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(podsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a pod and creates it. Returns the server's representation of the pod, and an error, if there is any.
+func (c *FakePods) Create(pod *corev1.Pod) (result *corev1.Pod, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(podsResource, c.ns, pod), &corev1.Pod{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Pod), err
+}
+
+// Update takes the representation of a pod and updates it. Returns the server's representation of the pod, and an error, if there is any.
+func (c *FakePods) Update(pod *corev1.Pod) (result *corev1.Pod, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(podsResource, c.ns, pod), &corev1.Pod{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Pod), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakePods) UpdateStatus(pod *corev1.Pod) (*corev1.Pod, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(podsResource, "status", c.ns, pod), &corev1.Pod{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Pod), err
+}
+
+// Delete takes name of the pod and deletes it. Returns an error if one occurs.
+func (c *FakePods) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(podsResource, c.ns, name), &corev1.Pod{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakePods) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(podsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &corev1.PodList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched pod.
+func (c *FakePods) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.Pod, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(podsResource, c.ns, name, pt, data, subresources...), &corev1.Pod{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Pod), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_pod_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_pod_expansion.go
new file mode 100644
index 000000000..b35d8aaa5
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_pod_expansion.go
@@ -0,0 +1,70 @@
+/*
+Copyright 2014 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 (
+ "k8s.io/api/core/v1"
+ policy "k8s.io/api/policy/v1beta1"
+ restclient "k8s.io/client-go/rest"
+ core "k8s.io/client-go/testing"
+)
+
+func (c *FakePods) Bind(binding *v1.Binding) error {
+ action := core.CreateActionImpl{}
+ action.Verb = "create"
+ action.Namespace = binding.Namespace
+ action.Resource = podsResource
+ action.Subresource = "binding"
+ action.Object = binding
+
+ _, err := c.Fake.Invokes(action, binding)
+ return err
+}
+
+func (c *FakePods) GetBinding(name string) (result *v1.Binding, err error) {
+ obj, err := c.Fake.
+ Invokes(core.NewGetSubresourceAction(podsResource, c.ns, "binding", name), &v1.Binding{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1.Binding), err
+}
+
+func (c *FakePods) GetLogs(name string, opts *v1.PodLogOptions) *restclient.Request {
+ action := core.GenericActionImpl{}
+ action.Verb = "get"
+ action.Namespace = c.ns
+ action.Resource = podsResource
+ action.Subresource = "log"
+ action.Value = opts
+
+ _, _ = c.Fake.Invokes(action, &v1.Pod{})
+ return &restclient.Request{}
+}
+
+func (c *FakePods) Evict(eviction *policy.Eviction) error {
+ action := core.CreateActionImpl{}
+ action.Verb = "create"
+ action.Namespace = c.ns
+ action.Resource = podsResource
+ action.Subresource = "eviction"
+ action.Object = eviction
+
+ _, err := c.Fake.Invokes(action, eviction)
+ return err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_podtemplate.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_podtemplate.go
new file mode 100644
index 000000000..307f30594
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_podtemplate.go
@@ -0,0 +1,128 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ corev1 "k8s.io/api/core/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakePodTemplates implements PodTemplateInterface
+type FakePodTemplates struct {
+ Fake *FakeCoreV1
+ ns string
+}
+
+var podtemplatesResource = schema.GroupVersionResource{Group: "", Version: "v1", Resource: "podtemplates"}
+
+var podtemplatesKind = schema.GroupVersionKind{Group: "", Version: "v1", Kind: "PodTemplate"}
+
+// Get takes name of the podTemplate, and returns the corresponding podTemplate object, and an error if there is any.
+func (c *FakePodTemplates) Get(name string, options v1.GetOptions) (result *corev1.PodTemplate, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(podtemplatesResource, c.ns, name), &corev1.PodTemplate{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.PodTemplate), err
+}
+
+// List takes label and field selectors, and returns the list of PodTemplates that match those selectors.
+func (c *FakePodTemplates) List(opts v1.ListOptions) (result *corev1.PodTemplateList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(podtemplatesResource, podtemplatesKind, c.ns, opts), &corev1.PodTemplateList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &corev1.PodTemplateList{ListMeta: obj.(*corev1.PodTemplateList).ListMeta}
+ for _, item := range obj.(*corev1.PodTemplateList).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 podTemplates.
+func (c *FakePodTemplates) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(podtemplatesResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a podTemplate and creates it. Returns the server's representation of the podTemplate, and an error, if there is any.
+func (c *FakePodTemplates) Create(podTemplate *corev1.PodTemplate) (result *corev1.PodTemplate, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(podtemplatesResource, c.ns, podTemplate), &corev1.PodTemplate{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.PodTemplate), err
+}
+
+// Update takes the representation of a podTemplate and updates it. Returns the server's representation of the podTemplate, and an error, if there is any.
+func (c *FakePodTemplates) Update(podTemplate *corev1.PodTemplate) (result *corev1.PodTemplate, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(podtemplatesResource, c.ns, podTemplate), &corev1.PodTemplate{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.PodTemplate), err
+}
+
+// Delete takes name of the podTemplate and deletes it. Returns an error if one occurs.
+func (c *FakePodTemplates) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(podtemplatesResource, c.ns, name), &corev1.PodTemplate{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakePodTemplates) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(podtemplatesResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &corev1.PodTemplateList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched podTemplate.
+func (c *FakePodTemplates) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.PodTemplate, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(podtemplatesResource, c.ns, name, pt, data, subresources...), &corev1.PodTemplate{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.PodTemplate), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_replicationcontroller.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_replicationcontroller.go
new file mode 100644
index 000000000..6de94c148
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_replicationcontroller.go
@@ -0,0 +1,163 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ autoscalingv1 "k8s.io/api/autoscaling/v1"
+ corev1 "k8s.io/api/core/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeReplicationControllers implements ReplicationControllerInterface
+type FakeReplicationControllers struct {
+ Fake *FakeCoreV1
+ ns string
+}
+
+var replicationcontrollersResource = schema.GroupVersionResource{Group: "", Version: "v1", Resource: "replicationcontrollers"}
+
+var replicationcontrollersKind = schema.GroupVersionKind{Group: "", Version: "v1", Kind: "ReplicationController"}
+
+// Get takes name of the replicationController, and returns the corresponding replicationController object, and an error if there is any.
+func (c *FakeReplicationControllers) Get(name string, options v1.GetOptions) (result *corev1.ReplicationController, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(replicationcontrollersResource, c.ns, name), &corev1.ReplicationController{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.ReplicationController), err
+}
+
+// List takes label and field selectors, and returns the list of ReplicationControllers that match those selectors.
+func (c *FakeReplicationControllers) List(opts v1.ListOptions) (result *corev1.ReplicationControllerList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(replicationcontrollersResource, replicationcontrollersKind, c.ns, opts), &corev1.ReplicationControllerList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &corev1.ReplicationControllerList{ListMeta: obj.(*corev1.ReplicationControllerList).ListMeta}
+ for _, item := range obj.(*corev1.ReplicationControllerList).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 replicationControllers.
+func (c *FakeReplicationControllers) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(replicationcontrollersResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a replicationController and creates it. Returns the server's representation of the replicationController, and an error, if there is any.
+func (c *FakeReplicationControllers) Create(replicationController *corev1.ReplicationController) (result *corev1.ReplicationController, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(replicationcontrollersResource, c.ns, replicationController), &corev1.ReplicationController{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.ReplicationController), err
+}
+
+// Update takes the representation of a replicationController and updates it. Returns the server's representation of the replicationController, and an error, if there is any.
+func (c *FakeReplicationControllers) Update(replicationController *corev1.ReplicationController) (result *corev1.ReplicationController, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(replicationcontrollersResource, c.ns, replicationController), &corev1.ReplicationController{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.ReplicationController), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeReplicationControllers) UpdateStatus(replicationController *corev1.ReplicationController) (*corev1.ReplicationController, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(replicationcontrollersResource, "status", c.ns, replicationController), &corev1.ReplicationController{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.ReplicationController), err
+}
+
+// Delete takes name of the replicationController and deletes it. Returns an error if one occurs.
+func (c *FakeReplicationControllers) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(replicationcontrollersResource, c.ns, name), &corev1.ReplicationController{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeReplicationControllers) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(replicationcontrollersResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &corev1.ReplicationControllerList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched replicationController.
+func (c *FakeReplicationControllers) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.ReplicationController, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(replicationcontrollersResource, c.ns, name, pt, data, subresources...), &corev1.ReplicationController{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.ReplicationController), err
+}
+
+// GetScale takes name of the replicationController, and returns the corresponding scale object, and an error if there is any.
+func (c *FakeReplicationControllers) GetScale(replicationControllerName string, options v1.GetOptions) (result *autoscalingv1.Scale, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetSubresourceAction(replicationcontrollersResource, c.ns, "scale", replicationControllerName), &autoscalingv1.Scale{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*autoscalingv1.Scale), err
+}
+
+// UpdateScale takes the representation of a scale and updates it. Returns the server's representation of the scale, and an error, if there is any.
+func (c *FakeReplicationControllers) UpdateScale(replicationControllerName string, scale *autoscalingv1.Scale) (result *autoscalingv1.Scale, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(replicationcontrollersResource, "scale", c.ns, scale), &autoscalingv1.Scale{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*autoscalingv1.Scale), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_resourcequota.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_resourcequota.go
new file mode 100644
index 000000000..b521f7120
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_resourcequota.go
@@ -0,0 +1,140 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ corev1 "k8s.io/api/core/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeResourceQuotas implements ResourceQuotaInterface
+type FakeResourceQuotas struct {
+ Fake *FakeCoreV1
+ ns string
+}
+
+var resourcequotasResource = schema.GroupVersionResource{Group: "", Version: "v1", Resource: "resourcequotas"}
+
+var resourcequotasKind = schema.GroupVersionKind{Group: "", Version: "v1", Kind: "ResourceQuota"}
+
+// Get takes name of the resourceQuota, and returns the corresponding resourceQuota object, and an error if there is any.
+func (c *FakeResourceQuotas) Get(name string, options v1.GetOptions) (result *corev1.ResourceQuota, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(resourcequotasResource, c.ns, name), &corev1.ResourceQuota{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.ResourceQuota), err
+}
+
+// List takes label and field selectors, and returns the list of ResourceQuotas that match those selectors.
+func (c *FakeResourceQuotas) List(opts v1.ListOptions) (result *corev1.ResourceQuotaList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(resourcequotasResource, resourcequotasKind, c.ns, opts), &corev1.ResourceQuotaList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &corev1.ResourceQuotaList{ListMeta: obj.(*corev1.ResourceQuotaList).ListMeta}
+ for _, item := range obj.(*corev1.ResourceQuotaList).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 resourceQuotas.
+func (c *FakeResourceQuotas) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(resourcequotasResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a resourceQuota and creates it. Returns the server's representation of the resourceQuota, and an error, if there is any.
+func (c *FakeResourceQuotas) Create(resourceQuota *corev1.ResourceQuota) (result *corev1.ResourceQuota, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(resourcequotasResource, c.ns, resourceQuota), &corev1.ResourceQuota{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.ResourceQuota), err
+}
+
+// Update takes the representation of a resourceQuota and updates it. Returns the server's representation of the resourceQuota, and an error, if there is any.
+func (c *FakeResourceQuotas) Update(resourceQuota *corev1.ResourceQuota) (result *corev1.ResourceQuota, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(resourcequotasResource, c.ns, resourceQuota), &corev1.ResourceQuota{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.ResourceQuota), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeResourceQuotas) UpdateStatus(resourceQuota *corev1.ResourceQuota) (*corev1.ResourceQuota, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(resourcequotasResource, "status", c.ns, resourceQuota), &corev1.ResourceQuota{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.ResourceQuota), err
+}
+
+// Delete takes name of the resourceQuota and deletes it. Returns an error if one occurs.
+func (c *FakeResourceQuotas) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(resourcequotasResource, c.ns, name), &corev1.ResourceQuota{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeResourceQuotas) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(resourcequotasResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &corev1.ResourceQuotaList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched resourceQuota.
+func (c *FakeResourceQuotas) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.ResourceQuota, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(resourcequotasResource, c.ns, name, pt, data, subresources...), &corev1.ResourceQuota{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.ResourceQuota), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_secret.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_secret.go
new file mode 100644
index 000000000..47dba9eff
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_secret.go
@@ -0,0 +1,128 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ corev1 "k8s.io/api/core/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeSecrets implements SecretInterface
+type FakeSecrets struct {
+ Fake *FakeCoreV1
+ ns string
+}
+
+var secretsResource = schema.GroupVersionResource{Group: "", Version: "v1", Resource: "secrets"}
+
+var secretsKind = schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Secret"}
+
+// Get takes name of the secret, and returns the corresponding secret object, and an error if there is any.
+func (c *FakeSecrets) Get(name string, options v1.GetOptions) (result *corev1.Secret, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(secretsResource, c.ns, name), &corev1.Secret{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Secret), err
+}
+
+// List takes label and field selectors, and returns the list of Secrets that match those selectors.
+func (c *FakeSecrets) List(opts v1.ListOptions) (result *corev1.SecretList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(secretsResource, secretsKind, c.ns, opts), &corev1.SecretList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &corev1.SecretList{ListMeta: obj.(*corev1.SecretList).ListMeta}
+ for _, item := range obj.(*corev1.SecretList).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 secrets.
+func (c *FakeSecrets) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(secretsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a secret and creates it. Returns the server's representation of the secret, and an error, if there is any.
+func (c *FakeSecrets) Create(secret *corev1.Secret) (result *corev1.Secret, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(secretsResource, c.ns, secret), &corev1.Secret{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Secret), err
+}
+
+// Update takes the representation of a secret and updates it. Returns the server's representation of the secret, and an error, if there is any.
+func (c *FakeSecrets) Update(secret *corev1.Secret) (result *corev1.Secret, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(secretsResource, c.ns, secret), &corev1.Secret{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Secret), err
+}
+
+// Delete takes name of the secret and deletes it. Returns an error if one occurs.
+func (c *FakeSecrets) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(secretsResource, c.ns, name), &corev1.Secret{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeSecrets) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(secretsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &corev1.SecretList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched secret.
+func (c *FakeSecrets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.Secret, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(secretsResource, c.ns, name, pt, data, subresources...), &corev1.Secret{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Secret), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_service.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_service.go
new file mode 100644
index 000000000..a65de4991
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_service.go
@@ -0,0 +1,132 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ corev1 "k8s.io/api/core/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeServices implements ServiceInterface
+type FakeServices struct {
+ Fake *FakeCoreV1
+ ns string
+}
+
+var servicesResource = schema.GroupVersionResource{Group: "", Version: "v1", Resource: "services"}
+
+var servicesKind = schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Service"}
+
+// Get takes name of the service, and returns the corresponding service object, and an error if there is any.
+func (c *FakeServices) Get(name string, options v1.GetOptions) (result *corev1.Service, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(servicesResource, c.ns, name), &corev1.Service{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Service), err
+}
+
+// List takes label and field selectors, and returns the list of Services that match those selectors.
+func (c *FakeServices) List(opts v1.ListOptions) (result *corev1.ServiceList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(servicesResource, servicesKind, c.ns, opts), &corev1.ServiceList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &corev1.ServiceList{ListMeta: obj.(*corev1.ServiceList).ListMeta}
+ for _, item := range obj.(*corev1.ServiceList).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 services.
+func (c *FakeServices) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(servicesResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a service and creates it. Returns the server's representation of the service, and an error, if there is any.
+func (c *FakeServices) Create(service *corev1.Service) (result *corev1.Service, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(servicesResource, c.ns, service), &corev1.Service{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Service), err
+}
+
+// Update takes the representation of a service and updates it. Returns the server's representation of the service, and an error, if there is any.
+func (c *FakeServices) Update(service *corev1.Service) (result *corev1.Service, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(servicesResource, c.ns, service), &corev1.Service{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Service), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeServices) UpdateStatus(service *corev1.Service) (*corev1.Service, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(servicesResource, "status", c.ns, service), &corev1.Service{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Service), err
+}
+
+// Delete takes name of the service and deletes it. Returns an error if one occurs.
+func (c *FakeServices) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(servicesResource, c.ns, name), &corev1.Service{})
+
+ return err
+}
+
+// Patch applies the patch and returns the patched service.
+func (c *FakeServices) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.Service, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(servicesResource, c.ns, name, pt, data, subresources...), &corev1.Service{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.Service), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_service_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_service_expansion.go
new file mode 100644
index 000000000..92e4930d7
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_service_expansion.go
@@ -0,0 +1,26 @@
+/*
+Copyright 2014 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 (
+ restclient "k8s.io/client-go/rest"
+ core "k8s.io/client-go/testing"
+)
+
+func (c *FakeServices) ProxyGet(scheme, name, port, path string, params map[string]string) restclient.ResponseWrapper {
+ return c.Fake.InvokesProxy(core.NewProxyGetAction(servicesResource, c.ns, scheme, name, port, path, params))
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_serviceaccount.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_serviceaccount.go
new file mode 100644
index 000000000..5b6d8f8be
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_serviceaccount.go
@@ -0,0 +1,128 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ corev1 "k8s.io/api/core/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeServiceAccounts implements ServiceAccountInterface
+type FakeServiceAccounts struct {
+ Fake *FakeCoreV1
+ ns string
+}
+
+var serviceaccountsResource = schema.GroupVersionResource{Group: "", Version: "v1", Resource: "serviceaccounts"}
+
+var serviceaccountsKind = schema.GroupVersionKind{Group: "", Version: "v1", Kind: "ServiceAccount"}
+
+// Get takes name of the serviceAccount, and returns the corresponding serviceAccount object, and an error if there is any.
+func (c *FakeServiceAccounts) Get(name string, options v1.GetOptions) (result *corev1.ServiceAccount, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(serviceaccountsResource, c.ns, name), &corev1.ServiceAccount{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.ServiceAccount), err
+}
+
+// List takes label and field selectors, and returns the list of ServiceAccounts that match those selectors.
+func (c *FakeServiceAccounts) List(opts v1.ListOptions) (result *corev1.ServiceAccountList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(serviceaccountsResource, serviceaccountsKind, c.ns, opts), &corev1.ServiceAccountList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &corev1.ServiceAccountList{ListMeta: obj.(*corev1.ServiceAccountList).ListMeta}
+ for _, item := range obj.(*corev1.ServiceAccountList).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 serviceAccounts.
+func (c *FakeServiceAccounts) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(serviceaccountsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a serviceAccount and creates it. Returns the server's representation of the serviceAccount, and an error, if there is any.
+func (c *FakeServiceAccounts) Create(serviceAccount *corev1.ServiceAccount) (result *corev1.ServiceAccount, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(serviceaccountsResource, c.ns, serviceAccount), &corev1.ServiceAccount{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.ServiceAccount), err
+}
+
+// Update takes the representation of a serviceAccount and updates it. Returns the server's representation of the serviceAccount, and an error, if there is any.
+func (c *FakeServiceAccounts) Update(serviceAccount *corev1.ServiceAccount) (result *corev1.ServiceAccount, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(serviceaccountsResource, c.ns, serviceAccount), &corev1.ServiceAccount{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.ServiceAccount), err
+}
+
+// Delete takes name of the serviceAccount and deletes it. Returns an error if one occurs.
+func (c *FakeServiceAccounts) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(serviceaccountsResource, c.ns, name), &corev1.ServiceAccount{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeServiceAccounts) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(serviceaccountsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &corev1.ServiceAccountList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched serviceAccount.
+func (c *FakeServiceAccounts) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.ServiceAccount, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(serviceaccountsResource, c.ns, name, pt, data, subresources...), &corev1.ServiceAccount{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*corev1.ServiceAccount), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_serviceaccount_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_serviceaccount_expansion.go
new file mode 100644
index 000000000..a0efbcc2f
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_serviceaccount_expansion.go
@@ -0,0 +1,31 @@
+/*
+Copyright 2018 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 (
+ authenticationv1 "k8s.io/api/authentication/v1"
+ core "k8s.io/client-go/testing"
+)
+
+func (c *FakeServiceAccounts) CreateToken(name string, tr *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) {
+ obj, err := c.Fake.Invokes(core.NewCreateSubresourceAction(serviceaccountsResource, name, "token", c.ns, tr), &authenticationv1.TokenRequest{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*authenticationv1.TokenRequest), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/fake_event.go b/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/fake_event.go
new file mode 100644
index 000000000..ef76ec131
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/fake_event.go
@@ -0,0 +1,128 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/api/events/v1beta1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeEvents implements EventInterface
+type FakeEvents struct {
+ Fake *FakeEventsV1beta1
+ ns string
+}
+
+var eventsResource = schema.GroupVersionResource{Group: "events.k8s.io", Version: "v1beta1", Resource: "events"}
+
+var eventsKind = schema.GroupVersionKind{Group: "events.k8s.io", Version: "v1beta1", Kind: "Event"}
+
+// Get takes name of the event, and returns the corresponding event object, and an error if there is any.
+func (c *FakeEvents) Get(name string, options v1.GetOptions) (result *v1beta1.Event, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(eventsResource, c.ns, name), &v1beta1.Event{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Event), err
+}
+
+// List takes label and field selectors, and returns the list of Events that match those selectors.
+func (c *FakeEvents) List(opts v1.ListOptions) (result *v1beta1.EventList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(eventsResource, eventsKind, c.ns, opts), &v1beta1.EventList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta1.EventList{ListMeta: obj.(*v1beta1.EventList).ListMeta}
+ for _, item := range obj.(*v1beta1.EventList).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 events.
+func (c *FakeEvents) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(eventsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a event and creates it. Returns the server's representation of the event, and an error, if there is any.
+func (c *FakeEvents) Create(event *v1beta1.Event) (result *v1beta1.Event, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(eventsResource, c.ns, event), &v1beta1.Event{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Event), err
+}
+
+// Update takes the representation of a event and updates it. Returns the server's representation of the event, and an error, if there is any.
+func (c *FakeEvents) Update(event *v1beta1.Event) (result *v1beta1.Event, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(eventsResource, c.ns, event), &v1beta1.Event{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Event), err
+}
+
+// Delete takes name of the event and deletes it. Returns an error if one occurs.
+func (c *FakeEvents) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(eventsResource, c.ns, name), &v1beta1.Event{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeEvents) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(eventsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta1.EventList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched event.
+func (c *FakeEvents) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.Event, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(eventsResource, c.ns, name, pt, data, subresources...), &v1beta1.Event{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Event), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/fake_event_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/fake_event_expansion.go
new file mode 100644
index 000000000..778843acd
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/fake_event_expansion.go
@@ -0,0 +1,66 @@
+/*
+Copyright 2014 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 (
+ v1beta1 "k8s.io/api/events/v1beta1"
+ types "k8s.io/apimachinery/pkg/types"
+ core "k8s.io/client-go/testing"
+)
+
+// CreateWithEventNamespace creats a new event. Returns the copy of the event the server returns, or an error.
+func (c *FakeEvents) CreateWithEventNamespace(event *v1beta1.Event) (*v1beta1.Event, error) {
+ action := core.NewRootCreateAction(eventsResource, event)
+ if c.ns != "" {
+ action = core.NewCreateAction(eventsResource, c.ns, event)
+ }
+ obj, err := c.Fake.Invokes(action, event)
+ if obj == nil {
+ return nil, err
+ }
+
+ return obj.(*v1beta1.Event), err
+}
+
+// UpdateWithEventNamespace replaces an existing event. Returns the copy of the event the server returns, or an error.
+func (c *FakeEvents) UpdateWithEventNamespace(event *v1beta1.Event) (*v1beta1.Event, error) {
+ action := core.NewRootUpdateAction(eventsResource, event)
+ if c.ns != "" {
+ action = core.NewUpdateAction(eventsResource, c.ns, event)
+ }
+ obj, err := c.Fake.Invokes(action, event)
+ if obj == nil {
+ return nil, err
+ }
+
+ return obj.(*v1beta1.Event), err
+}
+
+// PatchWithEventNamespace patches an existing event. Returns the copy of the event the server returns, or an error.
+func (c *FakeEvents) PatchWithEventNamespace(event *v1beta1.Event, data []byte) (*v1beta1.Event, error) {
+ pt := types.StrategicMergePatchType
+ action := core.NewRootPatchAction(eventsResource, event.Name, pt, data)
+ if c.ns != "" {
+ action = core.NewPatchAction(eventsResource, c.ns, event.Name, pt, data)
+ }
+ obj, err := c.Fake.Invokes(action, event)
+ if obj == nil {
+ return nil, err
+ }
+
+ return obj.(*v1beta1.Event), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/fake_events_client.go b/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/fake_events_client.go
new file mode 100644
index 000000000..875c774e3
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/fake_events_client.go
@@ -0,0 +1,40 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/client-go/kubernetes/typed/events/v1beta1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeEventsV1beta1 struct {
+ *testing.Fake
+}
+
+func (c *FakeEventsV1beta1) Events(namespace string) v1beta1.EventInterface {
+ return &FakeEvents{c, namespace}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeEventsV1beta1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_daemonset.go b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_daemonset.go
new file mode 100644
index 000000000..4c9866060
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_daemonset.go
@@ -0,0 +1,140 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/api/extensions/v1beta1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeDaemonSets implements DaemonSetInterface
+type FakeDaemonSets struct {
+ Fake *FakeExtensionsV1beta1
+ ns string
+}
+
+var daemonsetsResource = schema.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "daemonsets"}
+
+var daemonsetsKind = schema.GroupVersionKind{Group: "extensions", Version: "v1beta1", Kind: "DaemonSet"}
+
+// Get takes name of the daemonSet, and returns the corresponding daemonSet object, and an error if there is any.
+func (c *FakeDaemonSets) Get(name string, options v1.GetOptions) (result *v1beta1.DaemonSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(daemonsetsResource, c.ns, name), &v1beta1.DaemonSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.DaemonSet), err
+}
+
+// List takes label and field selectors, and returns the list of DaemonSets that match those selectors.
+func (c *FakeDaemonSets) List(opts v1.ListOptions) (result *v1beta1.DaemonSetList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(daemonsetsResource, daemonsetsKind, c.ns, opts), &v1beta1.DaemonSetList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta1.DaemonSetList{ListMeta: obj.(*v1beta1.DaemonSetList).ListMeta}
+ for _, item := range obj.(*v1beta1.DaemonSetList).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 daemonSets.
+func (c *FakeDaemonSets) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(daemonsetsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a daemonSet and creates it. Returns the server's representation of the daemonSet, and an error, if there is any.
+func (c *FakeDaemonSets) Create(daemonSet *v1beta1.DaemonSet) (result *v1beta1.DaemonSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(daemonsetsResource, c.ns, daemonSet), &v1beta1.DaemonSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.DaemonSet), err
+}
+
+// Update takes the representation of a daemonSet and updates it. Returns the server's representation of the daemonSet, and an error, if there is any.
+func (c *FakeDaemonSets) Update(daemonSet *v1beta1.DaemonSet) (result *v1beta1.DaemonSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(daemonsetsResource, c.ns, daemonSet), &v1beta1.DaemonSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.DaemonSet), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeDaemonSets) UpdateStatus(daemonSet *v1beta1.DaemonSet) (*v1beta1.DaemonSet, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(daemonsetsResource, "status", c.ns, daemonSet), &v1beta1.DaemonSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.DaemonSet), err
+}
+
+// Delete takes name of the daemonSet and deletes it. Returns an error if one occurs.
+func (c *FakeDaemonSets) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(daemonsetsResource, c.ns, name), &v1beta1.DaemonSet{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeDaemonSets) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(daemonsetsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta1.DaemonSetList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched daemonSet.
+func (c *FakeDaemonSets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.DaemonSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(daemonsetsResource, c.ns, name, pt, data, subresources...), &v1beta1.DaemonSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.DaemonSet), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_deployment.go b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_deployment.go
new file mode 100644
index 000000000..7b7df45cc
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_deployment.go
@@ -0,0 +1,162 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/api/extensions/v1beta1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeDeployments implements DeploymentInterface
+type FakeDeployments struct {
+ Fake *FakeExtensionsV1beta1
+ ns string
+}
+
+var deploymentsResource = schema.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "deployments"}
+
+var deploymentsKind = schema.GroupVersionKind{Group: "extensions", Version: "v1beta1", Kind: "Deployment"}
+
+// Get takes name of the deployment, and returns the corresponding deployment object, and an error if there is any.
+func (c *FakeDeployments) Get(name string, options v1.GetOptions) (result *v1beta1.Deployment, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(deploymentsResource, c.ns, name), &v1beta1.Deployment{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Deployment), err
+}
+
+// List takes label and field selectors, and returns the list of Deployments that match those selectors.
+func (c *FakeDeployments) List(opts v1.ListOptions) (result *v1beta1.DeploymentList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(deploymentsResource, deploymentsKind, c.ns, opts), &v1beta1.DeploymentList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta1.DeploymentList{ListMeta: obj.(*v1beta1.DeploymentList).ListMeta}
+ for _, item := range obj.(*v1beta1.DeploymentList).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 deployments.
+func (c *FakeDeployments) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(deploymentsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a deployment and creates it. Returns the server's representation of the deployment, and an error, if there is any.
+func (c *FakeDeployments) Create(deployment *v1beta1.Deployment) (result *v1beta1.Deployment, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(deploymentsResource, c.ns, deployment), &v1beta1.Deployment{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Deployment), err
+}
+
+// Update takes the representation of a deployment and updates it. Returns the server's representation of the deployment, and an error, if there is any.
+func (c *FakeDeployments) Update(deployment *v1beta1.Deployment) (result *v1beta1.Deployment, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(deploymentsResource, c.ns, deployment), &v1beta1.Deployment{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Deployment), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeDeployments) UpdateStatus(deployment *v1beta1.Deployment) (*v1beta1.Deployment, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(deploymentsResource, "status", c.ns, deployment), &v1beta1.Deployment{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Deployment), err
+}
+
+// Delete takes name of the deployment and deletes it. Returns an error if one occurs.
+func (c *FakeDeployments) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(deploymentsResource, c.ns, name), &v1beta1.Deployment{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeDeployments) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(deploymentsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta1.DeploymentList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched deployment.
+func (c *FakeDeployments) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.Deployment, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(deploymentsResource, c.ns, name, pt, data, subresources...), &v1beta1.Deployment{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Deployment), err
+}
+
+// GetScale takes name of the deployment, and returns the corresponding scale object, and an error if there is any.
+func (c *FakeDeployments) GetScale(deploymentName string, options v1.GetOptions) (result *v1beta1.Scale, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetSubresourceAction(deploymentsResource, c.ns, "scale", deploymentName), &v1beta1.Scale{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Scale), err
+}
+
+// UpdateScale takes the representation of a scale and updates it. Returns the server's representation of the scale, and an error, if there is any.
+func (c *FakeDeployments) UpdateScale(deploymentName string, scale *v1beta1.Scale) (result *v1beta1.Scale, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(deploymentsResource, "scale", c.ns, scale), &v1beta1.Scale{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Scale), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_deployment_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_deployment_expansion.go
new file mode 100644
index 000000000..af2bc0f71
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_deployment_expansion.go
@@ -0,0 +1,33 @@
+/*
+Copyright 2014 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 (
+ "k8s.io/api/extensions/v1beta1"
+ core "k8s.io/client-go/testing"
+)
+
+func (c *FakeDeployments) Rollback(deploymentRollback *v1beta1.DeploymentRollback) error {
+ action := core.CreateActionImpl{}
+ action.Verb = "create"
+ action.Resource = deploymentsResource
+ action.Subresource = "rollback"
+ action.Object = deploymentRollback
+
+ _, err := c.Fake.Invokes(action, deploymentRollback)
+ return err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_extensions_client.go b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_extensions_client.go
new file mode 100644
index 000000000..36c0d51bc
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_extensions_client.go
@@ -0,0 +1,60 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/client-go/kubernetes/typed/extensions/v1beta1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeExtensionsV1beta1 struct {
+ *testing.Fake
+}
+
+func (c *FakeExtensionsV1beta1) DaemonSets(namespace string) v1beta1.DaemonSetInterface {
+ return &FakeDaemonSets{c, namespace}
+}
+
+func (c *FakeExtensionsV1beta1) Deployments(namespace string) v1beta1.DeploymentInterface {
+ return &FakeDeployments{c, namespace}
+}
+
+func (c *FakeExtensionsV1beta1) Ingresses(namespace string) v1beta1.IngressInterface {
+ return &FakeIngresses{c, namespace}
+}
+
+func (c *FakeExtensionsV1beta1) NetworkPolicies(namespace string) v1beta1.NetworkPolicyInterface {
+ return &FakeNetworkPolicies{c, namespace}
+}
+
+func (c *FakeExtensionsV1beta1) PodSecurityPolicies() v1beta1.PodSecurityPolicyInterface {
+ return &FakePodSecurityPolicies{c}
+}
+
+func (c *FakeExtensionsV1beta1) ReplicaSets(namespace string) v1beta1.ReplicaSetInterface {
+ return &FakeReplicaSets{c, namespace}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeExtensionsV1beta1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_ingress.go b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_ingress.go
new file mode 100644
index 000000000..01c252140
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_ingress.go
@@ -0,0 +1,140 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/api/extensions/v1beta1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeIngresses implements IngressInterface
+type FakeIngresses struct {
+ Fake *FakeExtensionsV1beta1
+ ns string
+}
+
+var ingressesResource = schema.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "ingresses"}
+
+var ingressesKind = schema.GroupVersionKind{Group: "extensions", Version: "v1beta1", Kind: "Ingress"}
+
+// Get takes name of the ingress, and returns the corresponding ingress object, and an error if there is any.
+func (c *FakeIngresses) Get(name string, options v1.GetOptions) (result *v1beta1.Ingress, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(ingressesResource, c.ns, name), &v1beta1.Ingress{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Ingress), err
+}
+
+// List takes label and field selectors, and returns the list of Ingresses that match those selectors.
+func (c *FakeIngresses) List(opts v1.ListOptions) (result *v1beta1.IngressList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(ingressesResource, ingressesKind, c.ns, opts), &v1beta1.IngressList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta1.IngressList{ListMeta: obj.(*v1beta1.IngressList).ListMeta}
+ for _, item := range obj.(*v1beta1.IngressList).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 ingresses.
+func (c *FakeIngresses) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(ingressesResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a ingress and creates it. Returns the server's representation of the ingress, and an error, if there is any.
+func (c *FakeIngresses) Create(ingress *v1beta1.Ingress) (result *v1beta1.Ingress, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(ingressesResource, c.ns, ingress), &v1beta1.Ingress{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Ingress), err
+}
+
+// Update takes the representation of a ingress and updates it. Returns the server's representation of the ingress, and an error, if there is any.
+func (c *FakeIngresses) Update(ingress *v1beta1.Ingress) (result *v1beta1.Ingress, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(ingressesResource, c.ns, ingress), &v1beta1.Ingress{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Ingress), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeIngresses) UpdateStatus(ingress *v1beta1.Ingress) (*v1beta1.Ingress, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(ingressesResource, "status", c.ns, ingress), &v1beta1.Ingress{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Ingress), err
+}
+
+// Delete takes name of the ingress and deletes it. Returns an error if one occurs.
+func (c *FakeIngresses) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(ingressesResource, c.ns, name), &v1beta1.Ingress{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeIngresses) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(ingressesResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta1.IngressList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched ingress.
+func (c *FakeIngresses) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.Ingress, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(ingressesResource, c.ns, name, pt, data, subresources...), &v1beta1.Ingress{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Ingress), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_networkpolicy.go b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_networkpolicy.go
new file mode 100644
index 000000000..7f4d4a555
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_networkpolicy.go
@@ -0,0 +1,128 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/api/extensions/v1beta1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeNetworkPolicies implements NetworkPolicyInterface
+type FakeNetworkPolicies struct {
+ Fake *FakeExtensionsV1beta1
+ ns string
+}
+
+var networkpoliciesResource = schema.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "networkpolicies"}
+
+var networkpoliciesKind = schema.GroupVersionKind{Group: "extensions", Version: "v1beta1", Kind: "NetworkPolicy"}
+
+// Get takes name of the networkPolicy, and returns the corresponding networkPolicy object, and an error if there is any.
+func (c *FakeNetworkPolicies) Get(name string, options v1.GetOptions) (result *v1beta1.NetworkPolicy, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(networkpoliciesResource, c.ns, name), &v1beta1.NetworkPolicy{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.NetworkPolicy), err
+}
+
+// List takes label and field selectors, and returns the list of NetworkPolicies that match those selectors.
+func (c *FakeNetworkPolicies) List(opts v1.ListOptions) (result *v1beta1.NetworkPolicyList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(networkpoliciesResource, networkpoliciesKind, c.ns, opts), &v1beta1.NetworkPolicyList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta1.NetworkPolicyList{ListMeta: obj.(*v1beta1.NetworkPolicyList).ListMeta}
+ for _, item := range obj.(*v1beta1.NetworkPolicyList).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 networkPolicies.
+func (c *FakeNetworkPolicies) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(networkpoliciesResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a networkPolicy and creates it. Returns the server's representation of the networkPolicy, and an error, if there is any.
+func (c *FakeNetworkPolicies) Create(networkPolicy *v1beta1.NetworkPolicy) (result *v1beta1.NetworkPolicy, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(networkpoliciesResource, c.ns, networkPolicy), &v1beta1.NetworkPolicy{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.NetworkPolicy), err
+}
+
+// Update takes the representation of a networkPolicy and updates it. Returns the server's representation of the networkPolicy, and an error, if there is any.
+func (c *FakeNetworkPolicies) Update(networkPolicy *v1beta1.NetworkPolicy) (result *v1beta1.NetworkPolicy, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(networkpoliciesResource, c.ns, networkPolicy), &v1beta1.NetworkPolicy{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.NetworkPolicy), err
+}
+
+// Delete takes name of the networkPolicy and deletes it. Returns an error if one occurs.
+func (c *FakeNetworkPolicies) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(networkpoliciesResource, c.ns, name), &v1beta1.NetworkPolicy{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeNetworkPolicies) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(networkpoliciesResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta1.NetworkPolicyList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched networkPolicy.
+func (c *FakeNetworkPolicies) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.NetworkPolicy, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(networkpoliciesResource, c.ns, name, pt, data, subresources...), &v1beta1.NetworkPolicy{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.NetworkPolicy), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_podsecuritypolicy.go b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_podsecuritypolicy.go
new file mode 100644
index 000000000..b97a34416
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_podsecuritypolicy.go
@@ -0,0 +1,120 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/api/extensions/v1beta1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakePodSecurityPolicies implements PodSecurityPolicyInterface
+type FakePodSecurityPolicies struct {
+ Fake *FakeExtensionsV1beta1
+}
+
+var podsecuritypoliciesResource = schema.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "podsecuritypolicies"}
+
+var podsecuritypoliciesKind = schema.GroupVersionKind{Group: "extensions", Version: "v1beta1", Kind: "PodSecurityPolicy"}
+
+// Get takes name of the podSecurityPolicy, and returns the corresponding podSecurityPolicy object, and an error if there is any.
+func (c *FakePodSecurityPolicies) Get(name string, options v1.GetOptions) (result *v1beta1.PodSecurityPolicy, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootGetAction(podsecuritypoliciesResource, name), &v1beta1.PodSecurityPolicy{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.PodSecurityPolicy), err
+}
+
+// List takes label and field selectors, and returns the list of PodSecurityPolicies that match those selectors.
+func (c *FakePodSecurityPolicies) List(opts v1.ListOptions) (result *v1beta1.PodSecurityPolicyList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootListAction(podsecuritypoliciesResource, podsecuritypoliciesKind, opts), &v1beta1.PodSecurityPolicyList{})
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta1.PodSecurityPolicyList{ListMeta: obj.(*v1beta1.PodSecurityPolicyList).ListMeta}
+ for _, item := range obj.(*v1beta1.PodSecurityPolicyList).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 podSecurityPolicies.
+func (c *FakePodSecurityPolicies) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewRootWatchAction(podsecuritypoliciesResource, opts))
+}
+
+// Create takes the representation of a podSecurityPolicy and creates it. Returns the server's representation of the podSecurityPolicy, and an error, if there is any.
+func (c *FakePodSecurityPolicies) Create(podSecurityPolicy *v1beta1.PodSecurityPolicy) (result *v1beta1.PodSecurityPolicy, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootCreateAction(podsecuritypoliciesResource, podSecurityPolicy), &v1beta1.PodSecurityPolicy{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.PodSecurityPolicy), err
+}
+
+// Update takes the representation of a podSecurityPolicy and updates it. Returns the server's representation of the podSecurityPolicy, and an error, if there is any.
+func (c *FakePodSecurityPolicies) Update(podSecurityPolicy *v1beta1.PodSecurityPolicy) (result *v1beta1.PodSecurityPolicy, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateAction(podsecuritypoliciesResource, podSecurityPolicy), &v1beta1.PodSecurityPolicy{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.PodSecurityPolicy), err
+}
+
+// Delete takes name of the podSecurityPolicy and deletes it. Returns an error if one occurs.
+func (c *FakePodSecurityPolicies) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewRootDeleteAction(podsecuritypoliciesResource, name), &v1beta1.PodSecurityPolicy{})
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakePodSecurityPolicies) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewRootDeleteCollectionAction(podsecuritypoliciesResource, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta1.PodSecurityPolicyList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched podSecurityPolicy.
+func (c *FakePodSecurityPolicies) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.PodSecurityPolicy, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootPatchSubresourceAction(podsecuritypoliciesResource, name, pt, data, subresources...), &v1beta1.PodSecurityPolicy{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.PodSecurityPolicy), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_replicaset.go b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_replicaset.go
new file mode 100644
index 000000000..7ed16af90
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_replicaset.go
@@ -0,0 +1,162 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/api/extensions/v1beta1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeReplicaSets implements ReplicaSetInterface
+type FakeReplicaSets struct {
+ Fake *FakeExtensionsV1beta1
+ ns string
+}
+
+var replicasetsResource = schema.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "replicasets"}
+
+var replicasetsKind = schema.GroupVersionKind{Group: "extensions", Version: "v1beta1", Kind: "ReplicaSet"}
+
+// Get takes name of the replicaSet, and returns the corresponding replicaSet object, and an error if there is any.
+func (c *FakeReplicaSets) Get(name string, options v1.GetOptions) (result *v1beta1.ReplicaSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(replicasetsResource, c.ns, name), &v1beta1.ReplicaSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.ReplicaSet), err
+}
+
+// List takes label and field selectors, and returns the list of ReplicaSets that match those selectors.
+func (c *FakeReplicaSets) List(opts v1.ListOptions) (result *v1beta1.ReplicaSetList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(replicasetsResource, replicasetsKind, c.ns, opts), &v1beta1.ReplicaSetList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta1.ReplicaSetList{ListMeta: obj.(*v1beta1.ReplicaSetList).ListMeta}
+ for _, item := range obj.(*v1beta1.ReplicaSetList).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 replicaSets.
+func (c *FakeReplicaSets) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(replicasetsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a replicaSet and creates it. Returns the server's representation of the replicaSet, and an error, if there is any.
+func (c *FakeReplicaSets) Create(replicaSet *v1beta1.ReplicaSet) (result *v1beta1.ReplicaSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(replicasetsResource, c.ns, replicaSet), &v1beta1.ReplicaSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.ReplicaSet), err
+}
+
+// Update takes the representation of a replicaSet and updates it. Returns the server's representation of the replicaSet, and an error, if there is any.
+func (c *FakeReplicaSets) Update(replicaSet *v1beta1.ReplicaSet) (result *v1beta1.ReplicaSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(replicasetsResource, c.ns, replicaSet), &v1beta1.ReplicaSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.ReplicaSet), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeReplicaSets) UpdateStatus(replicaSet *v1beta1.ReplicaSet) (*v1beta1.ReplicaSet, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(replicasetsResource, "status", c.ns, replicaSet), &v1beta1.ReplicaSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.ReplicaSet), err
+}
+
+// Delete takes name of the replicaSet and deletes it. Returns an error if one occurs.
+func (c *FakeReplicaSets) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(replicasetsResource, c.ns, name), &v1beta1.ReplicaSet{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeReplicaSets) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(replicasetsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta1.ReplicaSetList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched replicaSet.
+func (c *FakeReplicaSets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.ReplicaSet, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(replicasetsResource, c.ns, name, pt, data, subresources...), &v1beta1.ReplicaSet{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.ReplicaSet), err
+}
+
+// GetScale takes name of the replicaSet, and returns the corresponding scale object, and an error if there is any.
+func (c *FakeReplicaSets) GetScale(replicaSetName string, options v1.GetOptions) (result *v1beta1.Scale, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetSubresourceAction(replicasetsResource, c.ns, "scale", replicaSetName), &v1beta1.Scale{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Scale), err
+}
+
+// UpdateScale takes the representation of a scale and updates it. Returns the server's representation of the scale, and an error, if there is any.
+func (c *FakeReplicaSets) UpdateScale(replicaSetName string, scale *v1beta1.Scale) (result *v1beta1.Scale, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(replicasetsResource, "scale", c.ns, scale), &v1beta1.Scale{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Scale), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/fake/fake_networking_client.go b/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/fake/fake_networking_client.go
new file mode 100644
index 000000000..6b135c636
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/fake/fake_networking_client.go
@@ -0,0 +1,40 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1 "k8s.io/client-go/kubernetes/typed/networking/v1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeNetworkingV1 struct {
+ *testing.Fake
+}
+
+func (c *FakeNetworkingV1) NetworkPolicies(namespace string) v1.NetworkPolicyInterface {
+ return &FakeNetworkPolicies{c, namespace}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeNetworkingV1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/fake/fake_networkpolicy.go b/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/fake/fake_networkpolicy.go
new file mode 100644
index 000000000..58667c481
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/fake/fake_networkpolicy.go
@@ -0,0 +1,128 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ networkingv1 "k8s.io/api/networking/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeNetworkPolicies implements NetworkPolicyInterface
+type FakeNetworkPolicies struct {
+ Fake *FakeNetworkingV1
+ ns string
+}
+
+var networkpoliciesResource = schema.GroupVersionResource{Group: "networking.k8s.io", Version: "v1", Resource: "networkpolicies"}
+
+var networkpoliciesKind = schema.GroupVersionKind{Group: "networking.k8s.io", Version: "v1", Kind: "NetworkPolicy"}
+
+// Get takes name of the networkPolicy, and returns the corresponding networkPolicy object, and an error if there is any.
+func (c *FakeNetworkPolicies) Get(name string, options v1.GetOptions) (result *networkingv1.NetworkPolicy, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(networkpoliciesResource, c.ns, name), &networkingv1.NetworkPolicy{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*networkingv1.NetworkPolicy), err
+}
+
+// List takes label and field selectors, and returns the list of NetworkPolicies that match those selectors.
+func (c *FakeNetworkPolicies) List(opts v1.ListOptions) (result *networkingv1.NetworkPolicyList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(networkpoliciesResource, networkpoliciesKind, c.ns, opts), &networkingv1.NetworkPolicyList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &networkingv1.NetworkPolicyList{ListMeta: obj.(*networkingv1.NetworkPolicyList).ListMeta}
+ for _, item := range obj.(*networkingv1.NetworkPolicyList).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 networkPolicies.
+func (c *FakeNetworkPolicies) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(networkpoliciesResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a networkPolicy and creates it. Returns the server's representation of the networkPolicy, and an error, if there is any.
+func (c *FakeNetworkPolicies) Create(networkPolicy *networkingv1.NetworkPolicy) (result *networkingv1.NetworkPolicy, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(networkpoliciesResource, c.ns, networkPolicy), &networkingv1.NetworkPolicy{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*networkingv1.NetworkPolicy), err
+}
+
+// Update takes the representation of a networkPolicy and updates it. Returns the server's representation of the networkPolicy, and an error, if there is any.
+func (c *FakeNetworkPolicies) Update(networkPolicy *networkingv1.NetworkPolicy) (result *networkingv1.NetworkPolicy, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(networkpoliciesResource, c.ns, networkPolicy), &networkingv1.NetworkPolicy{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*networkingv1.NetworkPolicy), err
+}
+
+// Delete takes name of the networkPolicy and deletes it. Returns an error if one occurs.
+func (c *FakeNetworkPolicies) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(networkpoliciesResource, c.ns, name), &networkingv1.NetworkPolicy{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeNetworkPolicies) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(networkpoliciesResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &networkingv1.NetworkPolicyList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched networkPolicy.
+func (c *FakeNetworkPolicies) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *networkingv1.NetworkPolicy, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(networkpoliciesResource, c.ns, name, pt, data, subresources...), &networkingv1.NetworkPolicy{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*networkingv1.NetworkPolicy), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/networking/v1beta1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/networking/v1beta1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/networking/v1beta1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/networking/v1beta1/fake/fake_ingress.go b/vendor/k8s.io/client-go/kubernetes/typed/networking/v1beta1/fake/fake_ingress.go
new file mode 100644
index 000000000..ee7821778
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/networking/v1beta1/fake/fake_ingress.go
@@ -0,0 +1,140 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/api/networking/v1beta1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeIngresses implements IngressInterface
+type FakeIngresses struct {
+ Fake *FakeNetworkingV1beta1
+ ns string
+}
+
+var ingressesResource = schema.GroupVersionResource{Group: "networking.k8s.io", Version: "v1beta1", Resource: "ingresses"}
+
+var ingressesKind = schema.GroupVersionKind{Group: "networking.k8s.io", Version: "v1beta1", Kind: "Ingress"}
+
+// Get takes name of the ingress, and returns the corresponding ingress object, and an error if there is any.
+func (c *FakeIngresses) Get(name string, options v1.GetOptions) (result *v1beta1.Ingress, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(ingressesResource, c.ns, name), &v1beta1.Ingress{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Ingress), err
+}
+
+// List takes label and field selectors, and returns the list of Ingresses that match those selectors.
+func (c *FakeIngresses) List(opts v1.ListOptions) (result *v1beta1.IngressList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(ingressesResource, ingressesKind, c.ns, opts), &v1beta1.IngressList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta1.IngressList{ListMeta: obj.(*v1beta1.IngressList).ListMeta}
+ for _, item := range obj.(*v1beta1.IngressList).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 ingresses.
+func (c *FakeIngresses) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(ingressesResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a ingress and creates it. Returns the server's representation of the ingress, and an error, if there is any.
+func (c *FakeIngresses) Create(ingress *v1beta1.Ingress) (result *v1beta1.Ingress, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(ingressesResource, c.ns, ingress), &v1beta1.Ingress{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Ingress), err
+}
+
+// Update takes the representation of a ingress and updates it. Returns the server's representation of the ingress, and an error, if there is any.
+func (c *FakeIngresses) Update(ingress *v1beta1.Ingress) (result *v1beta1.Ingress, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(ingressesResource, c.ns, ingress), &v1beta1.Ingress{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Ingress), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeIngresses) UpdateStatus(ingress *v1beta1.Ingress) (*v1beta1.Ingress, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(ingressesResource, "status", c.ns, ingress), &v1beta1.Ingress{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Ingress), err
+}
+
+// Delete takes name of the ingress and deletes it. Returns an error if one occurs.
+func (c *FakeIngresses) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(ingressesResource, c.ns, name), &v1beta1.Ingress{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeIngresses) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(ingressesResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta1.IngressList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched ingress.
+func (c *FakeIngresses) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.Ingress, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(ingressesResource, c.ns, name, pt, data, subresources...), &v1beta1.Ingress{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Ingress), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/networking/v1beta1/fake/fake_networking_client.go b/vendor/k8s.io/client-go/kubernetes/typed/networking/v1beta1/fake/fake_networking_client.go
new file mode 100644
index 000000000..bfe6fee68
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/networking/v1beta1/fake/fake_networking_client.go
@@ -0,0 +1,40 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/client-go/kubernetes/typed/networking/v1beta1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeNetworkingV1beta1 struct {
+ *testing.Fake
+}
+
+func (c *FakeNetworkingV1beta1) Ingresses(namespace string) v1beta1.IngressInterface {
+ return &FakeIngresses{c, namespace}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeNetworkingV1beta1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/node/v1alpha1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/node/v1alpha1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/node/v1alpha1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/node/v1alpha1/fake/fake_node_client.go b/vendor/k8s.io/client-go/kubernetes/typed/node/v1alpha1/fake/fake_node_client.go
new file mode 100644
index 000000000..21ab9de33
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/node/v1alpha1/fake/fake_node_client.go
@@ -0,0 +1,40 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1alpha1 "k8s.io/client-go/kubernetes/typed/node/v1alpha1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeNodeV1alpha1 struct {
+ *testing.Fake
+}
+
+func (c *FakeNodeV1alpha1) RuntimeClasses() v1alpha1.RuntimeClassInterface {
+ return &FakeRuntimeClasses{c}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeNodeV1alpha1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/node/v1alpha1/fake/fake_runtimeclass.go b/vendor/k8s.io/client-go/kubernetes/typed/node/v1alpha1/fake/fake_runtimeclass.go
new file mode 100644
index 000000000..3c8b00986
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/node/v1alpha1/fake/fake_runtimeclass.go
@@ -0,0 +1,120 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1alpha1 "k8s.io/api/node/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeRuntimeClasses implements RuntimeClassInterface
+type FakeRuntimeClasses struct {
+ Fake *FakeNodeV1alpha1
+}
+
+var runtimeclassesResource = schema.GroupVersionResource{Group: "node.k8s.io", Version: "v1alpha1", Resource: "runtimeclasses"}
+
+var runtimeclassesKind = schema.GroupVersionKind{Group: "node.k8s.io", Version: "v1alpha1", Kind: "RuntimeClass"}
+
+// Get takes name of the runtimeClass, and returns the corresponding runtimeClass object, and an error if there is any.
+func (c *FakeRuntimeClasses) Get(name string, options v1.GetOptions) (result *v1alpha1.RuntimeClass, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootGetAction(runtimeclassesResource, name), &v1alpha1.RuntimeClass{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.RuntimeClass), err
+}
+
+// List takes label and field selectors, and returns the list of RuntimeClasses that match those selectors.
+func (c *FakeRuntimeClasses) List(opts v1.ListOptions) (result *v1alpha1.RuntimeClassList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootListAction(runtimeclassesResource, runtimeclassesKind, opts), &v1alpha1.RuntimeClassList{})
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1alpha1.RuntimeClassList{ListMeta: obj.(*v1alpha1.RuntimeClassList).ListMeta}
+ for _, item := range obj.(*v1alpha1.RuntimeClassList).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 runtimeClasses.
+func (c *FakeRuntimeClasses) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewRootWatchAction(runtimeclassesResource, opts))
+}
+
+// Create takes the representation of a runtimeClass and creates it. Returns the server's representation of the runtimeClass, and an error, if there is any.
+func (c *FakeRuntimeClasses) Create(runtimeClass *v1alpha1.RuntimeClass) (result *v1alpha1.RuntimeClass, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootCreateAction(runtimeclassesResource, runtimeClass), &v1alpha1.RuntimeClass{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.RuntimeClass), err
+}
+
+// Update takes the representation of a runtimeClass and updates it. Returns the server's representation of the runtimeClass, and an error, if there is any.
+func (c *FakeRuntimeClasses) Update(runtimeClass *v1alpha1.RuntimeClass) (result *v1alpha1.RuntimeClass, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateAction(runtimeclassesResource, runtimeClass), &v1alpha1.RuntimeClass{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.RuntimeClass), err
+}
+
+// Delete takes name of the runtimeClass and deletes it. Returns an error if one occurs.
+func (c *FakeRuntimeClasses) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewRootDeleteAction(runtimeclassesResource, name), &v1alpha1.RuntimeClass{})
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeRuntimeClasses) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewRootDeleteCollectionAction(runtimeclassesResource, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1alpha1.RuntimeClassList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched runtimeClass.
+func (c *FakeRuntimeClasses) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.RuntimeClass, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootPatchSubresourceAction(runtimeclassesResource, name, pt, data, subresources...), &v1alpha1.RuntimeClass{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.RuntimeClass), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/node/v1beta1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/node/v1beta1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/node/v1beta1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/node/v1beta1/fake/fake_node_client.go b/vendor/k8s.io/client-go/kubernetes/typed/node/v1beta1/fake/fake_node_client.go
new file mode 100644
index 000000000..36976ce54
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/node/v1beta1/fake/fake_node_client.go
@@ -0,0 +1,40 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/client-go/kubernetes/typed/node/v1beta1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeNodeV1beta1 struct {
+ *testing.Fake
+}
+
+func (c *FakeNodeV1beta1) RuntimeClasses() v1beta1.RuntimeClassInterface {
+ return &FakeRuntimeClasses{c}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeNodeV1beta1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/node/v1beta1/fake/fake_runtimeclass.go b/vendor/k8s.io/client-go/kubernetes/typed/node/v1beta1/fake/fake_runtimeclass.go
new file mode 100644
index 000000000..201d74266
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/node/v1beta1/fake/fake_runtimeclass.go
@@ -0,0 +1,120 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/api/node/v1beta1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeRuntimeClasses implements RuntimeClassInterface
+type FakeRuntimeClasses struct {
+ Fake *FakeNodeV1beta1
+}
+
+var runtimeclassesResource = schema.GroupVersionResource{Group: "node.k8s.io", Version: "v1beta1", Resource: "runtimeclasses"}
+
+var runtimeclassesKind = schema.GroupVersionKind{Group: "node.k8s.io", Version: "v1beta1", Kind: "RuntimeClass"}
+
+// Get takes name of the runtimeClass, and returns the corresponding runtimeClass object, and an error if there is any.
+func (c *FakeRuntimeClasses) Get(name string, options v1.GetOptions) (result *v1beta1.RuntimeClass, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootGetAction(runtimeclassesResource, name), &v1beta1.RuntimeClass{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.RuntimeClass), err
+}
+
+// List takes label and field selectors, and returns the list of RuntimeClasses that match those selectors.
+func (c *FakeRuntimeClasses) List(opts v1.ListOptions) (result *v1beta1.RuntimeClassList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootListAction(runtimeclassesResource, runtimeclassesKind, opts), &v1beta1.RuntimeClassList{})
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta1.RuntimeClassList{ListMeta: obj.(*v1beta1.RuntimeClassList).ListMeta}
+ for _, item := range obj.(*v1beta1.RuntimeClassList).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 runtimeClasses.
+func (c *FakeRuntimeClasses) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewRootWatchAction(runtimeclassesResource, opts))
+}
+
+// Create takes the representation of a runtimeClass and creates it. Returns the server's representation of the runtimeClass, and an error, if there is any.
+func (c *FakeRuntimeClasses) Create(runtimeClass *v1beta1.RuntimeClass) (result *v1beta1.RuntimeClass, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootCreateAction(runtimeclassesResource, runtimeClass), &v1beta1.RuntimeClass{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.RuntimeClass), err
+}
+
+// Update takes the representation of a runtimeClass and updates it. Returns the server's representation of the runtimeClass, and an error, if there is any.
+func (c *FakeRuntimeClasses) Update(runtimeClass *v1beta1.RuntimeClass) (result *v1beta1.RuntimeClass, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateAction(runtimeclassesResource, runtimeClass), &v1beta1.RuntimeClass{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.RuntimeClass), err
+}
+
+// Delete takes name of the runtimeClass and deletes it. Returns an error if one occurs.
+func (c *FakeRuntimeClasses) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewRootDeleteAction(runtimeclassesResource, name), &v1beta1.RuntimeClass{})
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeRuntimeClasses) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewRootDeleteCollectionAction(runtimeclassesResource, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta1.RuntimeClassList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched runtimeClass.
+func (c *FakeRuntimeClasses) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.RuntimeClass, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootPatchSubresourceAction(runtimeclassesResource, name, pt, data, subresources...), &v1beta1.RuntimeClass{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.RuntimeClass), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_eviction.go b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_eviction.go
new file mode 100644
index 000000000..b8f6f3eae
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_eviction.go
@@ -0,0 +1,25 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+// FakeEvictions implements EvictionInterface
+type FakeEvictions struct {
+ Fake *FakePolicyV1beta1
+ ns string
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_eviction_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_eviction_expansion.go
new file mode 100644
index 000000000..d660d09e5
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_eviction_expansion.go
@@ -0,0 +1,35 @@
+/*
+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 (
+ policy "k8s.io/api/policy/v1beta1"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ core "k8s.io/client-go/testing"
+)
+
+func (c *FakeEvictions) Evict(eviction *policy.Eviction) error {
+ action := core.CreateActionImpl{}
+ action.Verb = "create"
+ action.Namespace = c.ns
+ action.Resource = schema.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}
+ action.Subresource = "eviction"
+ action.Object = eviction
+
+ _, err := c.Fake.Invokes(action, eviction)
+ return err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_poddisruptionbudget.go b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_poddisruptionbudget.go
new file mode 100644
index 000000000..5bfbbca47
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_poddisruptionbudget.go
@@ -0,0 +1,140 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/api/policy/v1beta1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakePodDisruptionBudgets implements PodDisruptionBudgetInterface
+type FakePodDisruptionBudgets struct {
+ Fake *FakePolicyV1beta1
+ ns string
+}
+
+var poddisruptionbudgetsResource = schema.GroupVersionResource{Group: "policy", Version: "v1beta1", Resource: "poddisruptionbudgets"}
+
+var poddisruptionbudgetsKind = schema.GroupVersionKind{Group: "policy", Version: "v1beta1", Kind: "PodDisruptionBudget"}
+
+// Get takes name of the podDisruptionBudget, and returns the corresponding podDisruptionBudget object, and an error if there is any.
+func (c *FakePodDisruptionBudgets) Get(name string, options v1.GetOptions) (result *v1beta1.PodDisruptionBudget, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(poddisruptionbudgetsResource, c.ns, name), &v1beta1.PodDisruptionBudget{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.PodDisruptionBudget), err
+}
+
+// List takes label and field selectors, and returns the list of PodDisruptionBudgets that match those selectors.
+func (c *FakePodDisruptionBudgets) List(opts v1.ListOptions) (result *v1beta1.PodDisruptionBudgetList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(poddisruptionbudgetsResource, poddisruptionbudgetsKind, c.ns, opts), &v1beta1.PodDisruptionBudgetList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta1.PodDisruptionBudgetList{ListMeta: obj.(*v1beta1.PodDisruptionBudgetList).ListMeta}
+ for _, item := range obj.(*v1beta1.PodDisruptionBudgetList).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 podDisruptionBudgets.
+func (c *FakePodDisruptionBudgets) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(poddisruptionbudgetsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a podDisruptionBudget and creates it. Returns the server's representation of the podDisruptionBudget, and an error, if there is any.
+func (c *FakePodDisruptionBudgets) Create(podDisruptionBudget *v1beta1.PodDisruptionBudget) (result *v1beta1.PodDisruptionBudget, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(poddisruptionbudgetsResource, c.ns, podDisruptionBudget), &v1beta1.PodDisruptionBudget{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.PodDisruptionBudget), err
+}
+
+// Update takes the representation of a podDisruptionBudget and updates it. Returns the server's representation of the podDisruptionBudget, and an error, if there is any.
+func (c *FakePodDisruptionBudgets) Update(podDisruptionBudget *v1beta1.PodDisruptionBudget) (result *v1beta1.PodDisruptionBudget, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(poddisruptionbudgetsResource, c.ns, podDisruptionBudget), &v1beta1.PodDisruptionBudget{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.PodDisruptionBudget), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakePodDisruptionBudgets) UpdateStatus(podDisruptionBudget *v1beta1.PodDisruptionBudget) (*v1beta1.PodDisruptionBudget, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(poddisruptionbudgetsResource, "status", c.ns, podDisruptionBudget), &v1beta1.PodDisruptionBudget{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.PodDisruptionBudget), err
+}
+
+// Delete takes name of the podDisruptionBudget and deletes it. Returns an error if one occurs.
+func (c *FakePodDisruptionBudgets) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(poddisruptionbudgetsResource, c.ns, name), &v1beta1.PodDisruptionBudget{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakePodDisruptionBudgets) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(poddisruptionbudgetsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta1.PodDisruptionBudgetList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched podDisruptionBudget.
+func (c *FakePodDisruptionBudgets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.PodDisruptionBudget, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(poddisruptionbudgetsResource, c.ns, name, pt, data, subresources...), &v1beta1.PodDisruptionBudget{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.PodDisruptionBudget), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_podsecuritypolicy.go b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_podsecuritypolicy.go
new file mode 100644
index 000000000..32d1989f3
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_podsecuritypolicy.go
@@ -0,0 +1,120 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/api/policy/v1beta1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakePodSecurityPolicies implements PodSecurityPolicyInterface
+type FakePodSecurityPolicies struct {
+ Fake *FakePolicyV1beta1
+}
+
+var podsecuritypoliciesResource = schema.GroupVersionResource{Group: "policy", Version: "v1beta1", Resource: "podsecuritypolicies"}
+
+var podsecuritypoliciesKind = schema.GroupVersionKind{Group: "policy", Version: "v1beta1", Kind: "PodSecurityPolicy"}
+
+// Get takes name of the podSecurityPolicy, and returns the corresponding podSecurityPolicy object, and an error if there is any.
+func (c *FakePodSecurityPolicies) Get(name string, options v1.GetOptions) (result *v1beta1.PodSecurityPolicy, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootGetAction(podsecuritypoliciesResource, name), &v1beta1.PodSecurityPolicy{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.PodSecurityPolicy), err
+}
+
+// List takes label and field selectors, and returns the list of PodSecurityPolicies that match those selectors.
+func (c *FakePodSecurityPolicies) List(opts v1.ListOptions) (result *v1beta1.PodSecurityPolicyList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootListAction(podsecuritypoliciesResource, podsecuritypoliciesKind, opts), &v1beta1.PodSecurityPolicyList{})
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta1.PodSecurityPolicyList{ListMeta: obj.(*v1beta1.PodSecurityPolicyList).ListMeta}
+ for _, item := range obj.(*v1beta1.PodSecurityPolicyList).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 podSecurityPolicies.
+func (c *FakePodSecurityPolicies) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewRootWatchAction(podsecuritypoliciesResource, opts))
+}
+
+// Create takes the representation of a podSecurityPolicy and creates it. Returns the server's representation of the podSecurityPolicy, and an error, if there is any.
+func (c *FakePodSecurityPolicies) Create(podSecurityPolicy *v1beta1.PodSecurityPolicy) (result *v1beta1.PodSecurityPolicy, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootCreateAction(podsecuritypoliciesResource, podSecurityPolicy), &v1beta1.PodSecurityPolicy{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.PodSecurityPolicy), err
+}
+
+// Update takes the representation of a podSecurityPolicy and updates it. Returns the server's representation of the podSecurityPolicy, and an error, if there is any.
+func (c *FakePodSecurityPolicies) Update(podSecurityPolicy *v1beta1.PodSecurityPolicy) (result *v1beta1.PodSecurityPolicy, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateAction(podsecuritypoliciesResource, podSecurityPolicy), &v1beta1.PodSecurityPolicy{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.PodSecurityPolicy), err
+}
+
+// Delete takes name of the podSecurityPolicy and deletes it. Returns an error if one occurs.
+func (c *FakePodSecurityPolicies) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewRootDeleteAction(podsecuritypoliciesResource, name), &v1beta1.PodSecurityPolicy{})
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakePodSecurityPolicies) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewRootDeleteCollectionAction(podsecuritypoliciesResource, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta1.PodSecurityPolicyList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched podSecurityPolicy.
+func (c *FakePodSecurityPolicies) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.PodSecurityPolicy, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootPatchSubresourceAction(podsecuritypoliciesResource, name, pt, data, subresources...), &v1beta1.PodSecurityPolicy{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.PodSecurityPolicy), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_policy_client.go b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_policy_client.go
new file mode 100644
index 000000000..9c780bf1f
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_policy_client.go
@@ -0,0 +1,48 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/client-go/kubernetes/typed/policy/v1beta1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakePolicyV1beta1 struct {
+ *testing.Fake
+}
+
+func (c *FakePolicyV1beta1) Evictions(namespace string) v1beta1.EvictionInterface {
+ return &FakeEvictions{c, namespace}
+}
+
+func (c *FakePolicyV1beta1) PodDisruptionBudgets(namespace string) v1beta1.PodDisruptionBudgetInterface {
+ return &FakePodDisruptionBudgets{c, namespace}
+}
+
+func (c *FakePolicyV1beta1) PodSecurityPolicies() v1beta1.PodSecurityPolicyInterface {
+ return &FakePodSecurityPolicies{c}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakePolicyV1beta1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_clusterrole.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_clusterrole.go
new file mode 100644
index 000000000..d57f33939
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_clusterrole.go
@@ -0,0 +1,120 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ rbacv1 "k8s.io/api/rbac/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeClusterRoles implements ClusterRoleInterface
+type FakeClusterRoles struct {
+ Fake *FakeRbacV1
+}
+
+var clusterrolesResource = schema.GroupVersionResource{Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "clusterroles"}
+
+var clusterrolesKind = schema.GroupVersionKind{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRole"}
+
+// Get takes name of the clusterRole, and returns the corresponding clusterRole object, and an error if there is any.
+func (c *FakeClusterRoles) Get(name string, options v1.GetOptions) (result *rbacv1.ClusterRole, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootGetAction(clusterrolesResource, name), &rbacv1.ClusterRole{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*rbacv1.ClusterRole), err
+}
+
+// List takes label and field selectors, and returns the list of ClusterRoles that match those selectors.
+func (c *FakeClusterRoles) List(opts v1.ListOptions) (result *rbacv1.ClusterRoleList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootListAction(clusterrolesResource, clusterrolesKind, opts), &rbacv1.ClusterRoleList{})
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &rbacv1.ClusterRoleList{ListMeta: obj.(*rbacv1.ClusterRoleList).ListMeta}
+ for _, item := range obj.(*rbacv1.ClusterRoleList).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 clusterRoles.
+func (c *FakeClusterRoles) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewRootWatchAction(clusterrolesResource, opts))
+}
+
+// Create takes the representation of a clusterRole and creates it. Returns the server's representation of the clusterRole, and an error, if there is any.
+func (c *FakeClusterRoles) Create(clusterRole *rbacv1.ClusterRole) (result *rbacv1.ClusterRole, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootCreateAction(clusterrolesResource, clusterRole), &rbacv1.ClusterRole{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*rbacv1.ClusterRole), err
+}
+
+// Update takes the representation of a clusterRole and updates it. Returns the server's representation of the clusterRole, and an error, if there is any.
+func (c *FakeClusterRoles) Update(clusterRole *rbacv1.ClusterRole) (result *rbacv1.ClusterRole, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateAction(clusterrolesResource, clusterRole), &rbacv1.ClusterRole{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*rbacv1.ClusterRole), err
+}
+
+// Delete takes name of the clusterRole and deletes it. Returns an error if one occurs.
+func (c *FakeClusterRoles) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewRootDeleteAction(clusterrolesResource, name), &rbacv1.ClusterRole{})
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeClusterRoles) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewRootDeleteCollectionAction(clusterrolesResource, listOptions)
+
+ _, err := c.Fake.Invokes(action, &rbacv1.ClusterRoleList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched clusterRole.
+func (c *FakeClusterRoles) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *rbacv1.ClusterRole, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootPatchSubresourceAction(clusterrolesResource, name, pt, data, subresources...), &rbacv1.ClusterRole{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*rbacv1.ClusterRole), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_clusterrolebinding.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_clusterrolebinding.go
new file mode 100644
index 000000000..878473ef3
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_clusterrolebinding.go
@@ -0,0 +1,120 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ rbacv1 "k8s.io/api/rbac/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeClusterRoleBindings implements ClusterRoleBindingInterface
+type FakeClusterRoleBindings struct {
+ Fake *FakeRbacV1
+}
+
+var clusterrolebindingsResource = schema.GroupVersionResource{Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "clusterrolebindings"}
+
+var clusterrolebindingsKind = schema.GroupVersionKind{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRoleBinding"}
+
+// Get takes name of the clusterRoleBinding, and returns the corresponding clusterRoleBinding object, and an error if there is any.
+func (c *FakeClusterRoleBindings) Get(name string, options v1.GetOptions) (result *rbacv1.ClusterRoleBinding, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootGetAction(clusterrolebindingsResource, name), &rbacv1.ClusterRoleBinding{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*rbacv1.ClusterRoleBinding), err
+}
+
+// List takes label and field selectors, and returns the list of ClusterRoleBindings that match those selectors.
+func (c *FakeClusterRoleBindings) List(opts v1.ListOptions) (result *rbacv1.ClusterRoleBindingList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootListAction(clusterrolebindingsResource, clusterrolebindingsKind, opts), &rbacv1.ClusterRoleBindingList{})
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &rbacv1.ClusterRoleBindingList{ListMeta: obj.(*rbacv1.ClusterRoleBindingList).ListMeta}
+ for _, item := range obj.(*rbacv1.ClusterRoleBindingList).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 clusterRoleBindings.
+func (c *FakeClusterRoleBindings) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewRootWatchAction(clusterrolebindingsResource, opts))
+}
+
+// Create takes the representation of a clusterRoleBinding and creates it. Returns the server's representation of the clusterRoleBinding, and an error, if there is any.
+func (c *FakeClusterRoleBindings) Create(clusterRoleBinding *rbacv1.ClusterRoleBinding) (result *rbacv1.ClusterRoleBinding, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootCreateAction(clusterrolebindingsResource, clusterRoleBinding), &rbacv1.ClusterRoleBinding{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*rbacv1.ClusterRoleBinding), err
+}
+
+// Update takes the representation of a clusterRoleBinding and updates it. Returns the server's representation of the clusterRoleBinding, and an error, if there is any.
+func (c *FakeClusterRoleBindings) Update(clusterRoleBinding *rbacv1.ClusterRoleBinding) (result *rbacv1.ClusterRoleBinding, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateAction(clusterrolebindingsResource, clusterRoleBinding), &rbacv1.ClusterRoleBinding{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*rbacv1.ClusterRoleBinding), err
+}
+
+// Delete takes name of the clusterRoleBinding and deletes it. Returns an error if one occurs.
+func (c *FakeClusterRoleBindings) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewRootDeleteAction(clusterrolebindingsResource, name), &rbacv1.ClusterRoleBinding{})
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeClusterRoleBindings) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewRootDeleteCollectionAction(clusterrolebindingsResource, listOptions)
+
+ _, err := c.Fake.Invokes(action, &rbacv1.ClusterRoleBindingList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched clusterRoleBinding.
+func (c *FakeClusterRoleBindings) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *rbacv1.ClusterRoleBinding, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootPatchSubresourceAction(clusterrolebindingsResource, name, pt, data, subresources...), &rbacv1.ClusterRoleBinding{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*rbacv1.ClusterRoleBinding), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_rbac_client.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_rbac_client.go
new file mode 100644
index 000000000..426fd70d6
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_rbac_client.go
@@ -0,0 +1,52 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1 "k8s.io/client-go/kubernetes/typed/rbac/v1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeRbacV1 struct {
+ *testing.Fake
+}
+
+func (c *FakeRbacV1) ClusterRoles() v1.ClusterRoleInterface {
+ return &FakeClusterRoles{c}
+}
+
+func (c *FakeRbacV1) ClusterRoleBindings() v1.ClusterRoleBindingInterface {
+ return &FakeClusterRoleBindings{c}
+}
+
+func (c *FakeRbacV1) Roles(namespace string) v1.RoleInterface {
+ return &FakeRoles{c, namespace}
+}
+
+func (c *FakeRbacV1) RoleBindings(namespace string) v1.RoleBindingInterface {
+ return &FakeRoleBindings{c, namespace}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeRbacV1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_role.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_role.go
new file mode 100644
index 000000000..78ef3192f
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_role.go
@@ -0,0 +1,128 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ rbacv1 "k8s.io/api/rbac/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeRoles implements RoleInterface
+type FakeRoles struct {
+ Fake *FakeRbacV1
+ ns string
+}
+
+var rolesResource = schema.GroupVersionResource{Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "roles"}
+
+var rolesKind = schema.GroupVersionKind{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "Role"}
+
+// Get takes name of the role, and returns the corresponding role object, and an error if there is any.
+func (c *FakeRoles) Get(name string, options v1.GetOptions) (result *rbacv1.Role, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(rolesResource, c.ns, name), &rbacv1.Role{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*rbacv1.Role), err
+}
+
+// List takes label and field selectors, and returns the list of Roles that match those selectors.
+func (c *FakeRoles) List(opts v1.ListOptions) (result *rbacv1.RoleList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(rolesResource, rolesKind, c.ns, opts), &rbacv1.RoleList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &rbacv1.RoleList{ListMeta: obj.(*rbacv1.RoleList).ListMeta}
+ for _, item := range obj.(*rbacv1.RoleList).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 roles.
+func (c *FakeRoles) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(rolesResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a role and creates it. Returns the server's representation of the role, and an error, if there is any.
+func (c *FakeRoles) Create(role *rbacv1.Role) (result *rbacv1.Role, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(rolesResource, c.ns, role), &rbacv1.Role{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*rbacv1.Role), err
+}
+
+// Update takes the representation of a role and updates it. Returns the server's representation of the role, and an error, if there is any.
+func (c *FakeRoles) Update(role *rbacv1.Role) (result *rbacv1.Role, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(rolesResource, c.ns, role), &rbacv1.Role{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*rbacv1.Role), err
+}
+
+// Delete takes name of the role and deletes it. Returns an error if one occurs.
+func (c *FakeRoles) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(rolesResource, c.ns, name), &rbacv1.Role{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeRoles) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(rolesResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &rbacv1.RoleList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched role.
+func (c *FakeRoles) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *rbacv1.Role, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(rolesResource, c.ns, name, pt, data, subresources...), &rbacv1.Role{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*rbacv1.Role), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_rolebinding.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_rolebinding.go
new file mode 100644
index 000000000..6c344cadf
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_rolebinding.go
@@ -0,0 +1,128 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ rbacv1 "k8s.io/api/rbac/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeRoleBindings implements RoleBindingInterface
+type FakeRoleBindings struct {
+ Fake *FakeRbacV1
+ ns string
+}
+
+var rolebindingsResource = schema.GroupVersionResource{Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "rolebindings"}
+
+var rolebindingsKind = schema.GroupVersionKind{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "RoleBinding"}
+
+// Get takes name of the roleBinding, and returns the corresponding roleBinding object, and an error if there is any.
+func (c *FakeRoleBindings) Get(name string, options v1.GetOptions) (result *rbacv1.RoleBinding, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(rolebindingsResource, c.ns, name), &rbacv1.RoleBinding{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*rbacv1.RoleBinding), err
+}
+
+// List takes label and field selectors, and returns the list of RoleBindings that match those selectors.
+func (c *FakeRoleBindings) List(opts v1.ListOptions) (result *rbacv1.RoleBindingList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(rolebindingsResource, rolebindingsKind, c.ns, opts), &rbacv1.RoleBindingList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &rbacv1.RoleBindingList{ListMeta: obj.(*rbacv1.RoleBindingList).ListMeta}
+ for _, item := range obj.(*rbacv1.RoleBindingList).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 roleBindings.
+func (c *FakeRoleBindings) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(rolebindingsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a roleBinding and creates it. Returns the server's representation of the roleBinding, and an error, if there is any.
+func (c *FakeRoleBindings) Create(roleBinding *rbacv1.RoleBinding) (result *rbacv1.RoleBinding, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(rolebindingsResource, c.ns, roleBinding), &rbacv1.RoleBinding{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*rbacv1.RoleBinding), err
+}
+
+// Update takes the representation of a roleBinding and updates it. Returns the server's representation of the roleBinding, and an error, if there is any.
+func (c *FakeRoleBindings) Update(roleBinding *rbacv1.RoleBinding) (result *rbacv1.RoleBinding, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(rolebindingsResource, c.ns, roleBinding), &rbacv1.RoleBinding{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*rbacv1.RoleBinding), err
+}
+
+// Delete takes name of the roleBinding and deletes it. Returns an error if one occurs.
+func (c *FakeRoleBindings) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(rolebindingsResource, c.ns, name), &rbacv1.RoleBinding{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeRoleBindings) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(rolebindingsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &rbacv1.RoleBindingList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched roleBinding.
+func (c *FakeRoleBindings) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *rbacv1.RoleBinding, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(rolebindingsResource, c.ns, name, pt, data, subresources...), &rbacv1.RoleBinding{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*rbacv1.RoleBinding), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_clusterrole.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_clusterrole.go
new file mode 100644
index 000000000..d2d1b1c74
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_clusterrole.go
@@ -0,0 +1,120 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1alpha1 "k8s.io/api/rbac/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeClusterRoles implements ClusterRoleInterface
+type FakeClusterRoles struct {
+ Fake *FakeRbacV1alpha1
+}
+
+var clusterrolesResource = schema.GroupVersionResource{Group: "rbac.authorization.k8s.io", Version: "v1alpha1", Resource: "clusterroles"}
+
+var clusterrolesKind = schema.GroupVersionKind{Group: "rbac.authorization.k8s.io", Version: "v1alpha1", Kind: "ClusterRole"}
+
+// Get takes name of the clusterRole, and returns the corresponding clusterRole object, and an error if there is any.
+func (c *FakeClusterRoles) Get(name string, options v1.GetOptions) (result *v1alpha1.ClusterRole, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootGetAction(clusterrolesResource, name), &v1alpha1.ClusterRole{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.ClusterRole), err
+}
+
+// List takes label and field selectors, and returns the list of ClusterRoles that match those selectors.
+func (c *FakeClusterRoles) List(opts v1.ListOptions) (result *v1alpha1.ClusterRoleList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootListAction(clusterrolesResource, clusterrolesKind, opts), &v1alpha1.ClusterRoleList{})
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1alpha1.ClusterRoleList{ListMeta: obj.(*v1alpha1.ClusterRoleList).ListMeta}
+ for _, item := range obj.(*v1alpha1.ClusterRoleList).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 clusterRoles.
+func (c *FakeClusterRoles) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewRootWatchAction(clusterrolesResource, opts))
+}
+
+// Create takes the representation of a clusterRole and creates it. Returns the server's representation of the clusterRole, and an error, if there is any.
+func (c *FakeClusterRoles) Create(clusterRole *v1alpha1.ClusterRole) (result *v1alpha1.ClusterRole, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootCreateAction(clusterrolesResource, clusterRole), &v1alpha1.ClusterRole{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.ClusterRole), err
+}
+
+// Update takes the representation of a clusterRole and updates it. Returns the server's representation of the clusterRole, and an error, if there is any.
+func (c *FakeClusterRoles) Update(clusterRole *v1alpha1.ClusterRole) (result *v1alpha1.ClusterRole, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateAction(clusterrolesResource, clusterRole), &v1alpha1.ClusterRole{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.ClusterRole), err
+}
+
+// Delete takes name of the clusterRole and deletes it. Returns an error if one occurs.
+func (c *FakeClusterRoles) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewRootDeleteAction(clusterrolesResource, name), &v1alpha1.ClusterRole{})
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeClusterRoles) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewRootDeleteCollectionAction(clusterrolesResource, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1alpha1.ClusterRoleList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched clusterRole.
+func (c *FakeClusterRoles) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.ClusterRole, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootPatchSubresourceAction(clusterrolesResource, name, pt, data, subresources...), &v1alpha1.ClusterRole{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.ClusterRole), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_clusterrolebinding.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_clusterrolebinding.go
new file mode 100644
index 000000000..3e23e5f65
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_clusterrolebinding.go
@@ -0,0 +1,120 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1alpha1 "k8s.io/api/rbac/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeClusterRoleBindings implements ClusterRoleBindingInterface
+type FakeClusterRoleBindings struct {
+ Fake *FakeRbacV1alpha1
+}
+
+var clusterrolebindingsResource = schema.GroupVersionResource{Group: "rbac.authorization.k8s.io", Version: "v1alpha1", Resource: "clusterrolebindings"}
+
+var clusterrolebindingsKind = schema.GroupVersionKind{Group: "rbac.authorization.k8s.io", Version: "v1alpha1", Kind: "ClusterRoleBinding"}
+
+// Get takes name of the clusterRoleBinding, and returns the corresponding clusterRoleBinding object, and an error if there is any.
+func (c *FakeClusterRoleBindings) Get(name string, options v1.GetOptions) (result *v1alpha1.ClusterRoleBinding, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootGetAction(clusterrolebindingsResource, name), &v1alpha1.ClusterRoleBinding{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.ClusterRoleBinding), err
+}
+
+// List takes label and field selectors, and returns the list of ClusterRoleBindings that match those selectors.
+func (c *FakeClusterRoleBindings) List(opts v1.ListOptions) (result *v1alpha1.ClusterRoleBindingList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootListAction(clusterrolebindingsResource, clusterrolebindingsKind, opts), &v1alpha1.ClusterRoleBindingList{})
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1alpha1.ClusterRoleBindingList{ListMeta: obj.(*v1alpha1.ClusterRoleBindingList).ListMeta}
+ for _, item := range obj.(*v1alpha1.ClusterRoleBindingList).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 clusterRoleBindings.
+func (c *FakeClusterRoleBindings) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewRootWatchAction(clusterrolebindingsResource, opts))
+}
+
+// Create takes the representation of a clusterRoleBinding and creates it. Returns the server's representation of the clusterRoleBinding, and an error, if there is any.
+func (c *FakeClusterRoleBindings) Create(clusterRoleBinding *v1alpha1.ClusterRoleBinding) (result *v1alpha1.ClusterRoleBinding, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootCreateAction(clusterrolebindingsResource, clusterRoleBinding), &v1alpha1.ClusterRoleBinding{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.ClusterRoleBinding), err
+}
+
+// Update takes the representation of a clusterRoleBinding and updates it. Returns the server's representation of the clusterRoleBinding, and an error, if there is any.
+func (c *FakeClusterRoleBindings) Update(clusterRoleBinding *v1alpha1.ClusterRoleBinding) (result *v1alpha1.ClusterRoleBinding, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateAction(clusterrolebindingsResource, clusterRoleBinding), &v1alpha1.ClusterRoleBinding{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.ClusterRoleBinding), err
+}
+
+// Delete takes name of the clusterRoleBinding and deletes it. Returns an error if one occurs.
+func (c *FakeClusterRoleBindings) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewRootDeleteAction(clusterrolebindingsResource, name), &v1alpha1.ClusterRoleBinding{})
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeClusterRoleBindings) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewRootDeleteCollectionAction(clusterrolebindingsResource, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1alpha1.ClusterRoleBindingList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched clusterRoleBinding.
+func (c *FakeClusterRoleBindings) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.ClusterRoleBinding, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootPatchSubresourceAction(clusterrolebindingsResource, name, pt, data, subresources...), &v1alpha1.ClusterRoleBinding{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.ClusterRoleBinding), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_rbac_client.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_rbac_client.go
new file mode 100644
index 000000000..3447e9be8
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_rbac_client.go
@@ -0,0 +1,52 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1alpha1 "k8s.io/client-go/kubernetes/typed/rbac/v1alpha1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeRbacV1alpha1 struct {
+ *testing.Fake
+}
+
+func (c *FakeRbacV1alpha1) ClusterRoles() v1alpha1.ClusterRoleInterface {
+ return &FakeClusterRoles{c}
+}
+
+func (c *FakeRbacV1alpha1) ClusterRoleBindings() v1alpha1.ClusterRoleBindingInterface {
+ return &FakeClusterRoleBindings{c}
+}
+
+func (c *FakeRbacV1alpha1) Roles(namespace string) v1alpha1.RoleInterface {
+ return &FakeRoles{c, namespace}
+}
+
+func (c *FakeRbacV1alpha1) RoleBindings(namespace string) v1alpha1.RoleBindingInterface {
+ return &FakeRoleBindings{c, namespace}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeRbacV1alpha1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_role.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_role.go
new file mode 100644
index 000000000..7bd52373f
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_role.go
@@ -0,0 +1,128 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1alpha1 "k8s.io/api/rbac/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeRoles implements RoleInterface
+type FakeRoles struct {
+ Fake *FakeRbacV1alpha1
+ ns string
+}
+
+var rolesResource = schema.GroupVersionResource{Group: "rbac.authorization.k8s.io", Version: "v1alpha1", Resource: "roles"}
+
+var rolesKind = schema.GroupVersionKind{Group: "rbac.authorization.k8s.io", Version: "v1alpha1", Kind: "Role"}
+
+// Get takes name of the role, and returns the corresponding role object, and an error if there is any.
+func (c *FakeRoles) Get(name string, options v1.GetOptions) (result *v1alpha1.Role, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(rolesResource, c.ns, name), &v1alpha1.Role{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.Role), err
+}
+
+// List takes label and field selectors, and returns the list of Roles that match those selectors.
+func (c *FakeRoles) List(opts v1.ListOptions) (result *v1alpha1.RoleList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(rolesResource, rolesKind, c.ns, opts), &v1alpha1.RoleList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1alpha1.RoleList{ListMeta: obj.(*v1alpha1.RoleList).ListMeta}
+ for _, item := range obj.(*v1alpha1.RoleList).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 roles.
+func (c *FakeRoles) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(rolesResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a role and creates it. Returns the server's representation of the role, and an error, if there is any.
+func (c *FakeRoles) Create(role *v1alpha1.Role) (result *v1alpha1.Role, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(rolesResource, c.ns, role), &v1alpha1.Role{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.Role), err
+}
+
+// Update takes the representation of a role and updates it. Returns the server's representation of the role, and an error, if there is any.
+func (c *FakeRoles) Update(role *v1alpha1.Role) (result *v1alpha1.Role, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(rolesResource, c.ns, role), &v1alpha1.Role{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.Role), err
+}
+
+// Delete takes name of the role and deletes it. Returns an error if one occurs.
+func (c *FakeRoles) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(rolesResource, c.ns, name), &v1alpha1.Role{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeRoles) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(rolesResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1alpha1.RoleList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched role.
+func (c *FakeRoles) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Role, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(rolesResource, c.ns, name, pt, data, subresources...), &v1alpha1.Role{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.Role), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_rolebinding.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_rolebinding.go
new file mode 100644
index 000000000..015050311
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_rolebinding.go
@@ -0,0 +1,128 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1alpha1 "k8s.io/api/rbac/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeRoleBindings implements RoleBindingInterface
+type FakeRoleBindings struct {
+ Fake *FakeRbacV1alpha1
+ ns string
+}
+
+var rolebindingsResource = schema.GroupVersionResource{Group: "rbac.authorization.k8s.io", Version: "v1alpha1", Resource: "rolebindings"}
+
+var rolebindingsKind = schema.GroupVersionKind{Group: "rbac.authorization.k8s.io", Version: "v1alpha1", Kind: "RoleBinding"}
+
+// Get takes name of the roleBinding, and returns the corresponding roleBinding object, and an error if there is any.
+func (c *FakeRoleBindings) Get(name string, options v1.GetOptions) (result *v1alpha1.RoleBinding, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(rolebindingsResource, c.ns, name), &v1alpha1.RoleBinding{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.RoleBinding), err
+}
+
+// List takes label and field selectors, and returns the list of RoleBindings that match those selectors.
+func (c *FakeRoleBindings) List(opts v1.ListOptions) (result *v1alpha1.RoleBindingList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(rolebindingsResource, rolebindingsKind, c.ns, opts), &v1alpha1.RoleBindingList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1alpha1.RoleBindingList{ListMeta: obj.(*v1alpha1.RoleBindingList).ListMeta}
+ for _, item := range obj.(*v1alpha1.RoleBindingList).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 roleBindings.
+func (c *FakeRoleBindings) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(rolebindingsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a roleBinding and creates it. Returns the server's representation of the roleBinding, and an error, if there is any.
+func (c *FakeRoleBindings) Create(roleBinding *v1alpha1.RoleBinding) (result *v1alpha1.RoleBinding, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(rolebindingsResource, c.ns, roleBinding), &v1alpha1.RoleBinding{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.RoleBinding), err
+}
+
+// Update takes the representation of a roleBinding and updates it. Returns the server's representation of the roleBinding, and an error, if there is any.
+func (c *FakeRoleBindings) Update(roleBinding *v1alpha1.RoleBinding) (result *v1alpha1.RoleBinding, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(rolebindingsResource, c.ns, roleBinding), &v1alpha1.RoleBinding{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.RoleBinding), err
+}
+
+// Delete takes name of the roleBinding and deletes it. Returns an error if one occurs.
+func (c *FakeRoleBindings) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(rolebindingsResource, c.ns, name), &v1alpha1.RoleBinding{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeRoleBindings) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(rolebindingsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1alpha1.RoleBindingList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched roleBinding.
+func (c *FakeRoleBindings) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.RoleBinding, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(rolebindingsResource, c.ns, name, pt, data, subresources...), &v1alpha1.RoleBinding{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.RoleBinding), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_clusterrole.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_clusterrole.go
new file mode 100644
index 000000000..2dbc3f616
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_clusterrole.go
@@ -0,0 +1,120 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/api/rbac/v1beta1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeClusterRoles implements ClusterRoleInterface
+type FakeClusterRoles struct {
+ Fake *FakeRbacV1beta1
+}
+
+var clusterrolesResource = schema.GroupVersionResource{Group: "rbac.authorization.k8s.io", Version: "v1beta1", Resource: "clusterroles"}
+
+var clusterrolesKind = schema.GroupVersionKind{Group: "rbac.authorization.k8s.io", Version: "v1beta1", Kind: "ClusterRole"}
+
+// Get takes name of the clusterRole, and returns the corresponding clusterRole object, and an error if there is any.
+func (c *FakeClusterRoles) Get(name string, options v1.GetOptions) (result *v1beta1.ClusterRole, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootGetAction(clusterrolesResource, name), &v1beta1.ClusterRole{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.ClusterRole), err
+}
+
+// List takes label and field selectors, and returns the list of ClusterRoles that match those selectors.
+func (c *FakeClusterRoles) List(opts v1.ListOptions) (result *v1beta1.ClusterRoleList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootListAction(clusterrolesResource, clusterrolesKind, opts), &v1beta1.ClusterRoleList{})
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta1.ClusterRoleList{ListMeta: obj.(*v1beta1.ClusterRoleList).ListMeta}
+ for _, item := range obj.(*v1beta1.ClusterRoleList).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 clusterRoles.
+func (c *FakeClusterRoles) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewRootWatchAction(clusterrolesResource, opts))
+}
+
+// Create takes the representation of a clusterRole and creates it. Returns the server's representation of the clusterRole, and an error, if there is any.
+func (c *FakeClusterRoles) Create(clusterRole *v1beta1.ClusterRole) (result *v1beta1.ClusterRole, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootCreateAction(clusterrolesResource, clusterRole), &v1beta1.ClusterRole{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.ClusterRole), err
+}
+
+// Update takes the representation of a clusterRole and updates it. Returns the server's representation of the clusterRole, and an error, if there is any.
+func (c *FakeClusterRoles) Update(clusterRole *v1beta1.ClusterRole) (result *v1beta1.ClusterRole, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateAction(clusterrolesResource, clusterRole), &v1beta1.ClusterRole{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.ClusterRole), err
+}
+
+// Delete takes name of the clusterRole and deletes it. Returns an error if one occurs.
+func (c *FakeClusterRoles) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewRootDeleteAction(clusterrolesResource, name), &v1beta1.ClusterRole{})
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeClusterRoles) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewRootDeleteCollectionAction(clusterrolesResource, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta1.ClusterRoleList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched clusterRole.
+func (c *FakeClusterRoles) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.ClusterRole, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootPatchSubresourceAction(clusterrolesResource, name, pt, data, subresources...), &v1beta1.ClusterRole{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.ClusterRole), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_clusterrolebinding.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_clusterrolebinding.go
new file mode 100644
index 000000000..14e20bc28
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_clusterrolebinding.go
@@ -0,0 +1,120 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/api/rbac/v1beta1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeClusterRoleBindings implements ClusterRoleBindingInterface
+type FakeClusterRoleBindings struct {
+ Fake *FakeRbacV1beta1
+}
+
+var clusterrolebindingsResource = schema.GroupVersionResource{Group: "rbac.authorization.k8s.io", Version: "v1beta1", Resource: "clusterrolebindings"}
+
+var clusterrolebindingsKind = schema.GroupVersionKind{Group: "rbac.authorization.k8s.io", Version: "v1beta1", Kind: "ClusterRoleBinding"}
+
+// Get takes name of the clusterRoleBinding, and returns the corresponding clusterRoleBinding object, and an error if there is any.
+func (c *FakeClusterRoleBindings) Get(name string, options v1.GetOptions) (result *v1beta1.ClusterRoleBinding, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootGetAction(clusterrolebindingsResource, name), &v1beta1.ClusterRoleBinding{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.ClusterRoleBinding), err
+}
+
+// List takes label and field selectors, and returns the list of ClusterRoleBindings that match those selectors.
+func (c *FakeClusterRoleBindings) List(opts v1.ListOptions) (result *v1beta1.ClusterRoleBindingList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootListAction(clusterrolebindingsResource, clusterrolebindingsKind, opts), &v1beta1.ClusterRoleBindingList{})
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta1.ClusterRoleBindingList{ListMeta: obj.(*v1beta1.ClusterRoleBindingList).ListMeta}
+ for _, item := range obj.(*v1beta1.ClusterRoleBindingList).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 clusterRoleBindings.
+func (c *FakeClusterRoleBindings) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewRootWatchAction(clusterrolebindingsResource, opts))
+}
+
+// Create takes the representation of a clusterRoleBinding and creates it. Returns the server's representation of the clusterRoleBinding, and an error, if there is any.
+func (c *FakeClusterRoleBindings) Create(clusterRoleBinding *v1beta1.ClusterRoleBinding) (result *v1beta1.ClusterRoleBinding, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootCreateAction(clusterrolebindingsResource, clusterRoleBinding), &v1beta1.ClusterRoleBinding{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.ClusterRoleBinding), err
+}
+
+// Update takes the representation of a clusterRoleBinding and updates it. Returns the server's representation of the clusterRoleBinding, and an error, if there is any.
+func (c *FakeClusterRoleBindings) Update(clusterRoleBinding *v1beta1.ClusterRoleBinding) (result *v1beta1.ClusterRoleBinding, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateAction(clusterrolebindingsResource, clusterRoleBinding), &v1beta1.ClusterRoleBinding{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.ClusterRoleBinding), err
+}
+
+// Delete takes name of the clusterRoleBinding and deletes it. Returns an error if one occurs.
+func (c *FakeClusterRoleBindings) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewRootDeleteAction(clusterrolebindingsResource, name), &v1beta1.ClusterRoleBinding{})
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeClusterRoleBindings) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewRootDeleteCollectionAction(clusterrolebindingsResource, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta1.ClusterRoleBindingList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched clusterRoleBinding.
+func (c *FakeClusterRoleBindings) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.ClusterRoleBinding, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootPatchSubresourceAction(clusterrolebindingsResource, name, pt, data, subresources...), &v1beta1.ClusterRoleBinding{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.ClusterRoleBinding), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_rbac_client.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_rbac_client.go
new file mode 100644
index 000000000..bdbc246b7
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_rbac_client.go
@@ -0,0 +1,52 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/client-go/kubernetes/typed/rbac/v1beta1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeRbacV1beta1 struct {
+ *testing.Fake
+}
+
+func (c *FakeRbacV1beta1) ClusterRoles() v1beta1.ClusterRoleInterface {
+ return &FakeClusterRoles{c}
+}
+
+func (c *FakeRbacV1beta1) ClusterRoleBindings() v1beta1.ClusterRoleBindingInterface {
+ return &FakeClusterRoleBindings{c}
+}
+
+func (c *FakeRbacV1beta1) Roles(namespace string) v1beta1.RoleInterface {
+ return &FakeRoles{c, namespace}
+}
+
+func (c *FakeRbacV1beta1) RoleBindings(namespace string) v1beta1.RoleBindingInterface {
+ return &FakeRoleBindings{c, namespace}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeRbacV1beta1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_role.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_role.go
new file mode 100644
index 000000000..e31768e4e
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_role.go
@@ -0,0 +1,128 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/api/rbac/v1beta1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeRoles implements RoleInterface
+type FakeRoles struct {
+ Fake *FakeRbacV1beta1
+ ns string
+}
+
+var rolesResource = schema.GroupVersionResource{Group: "rbac.authorization.k8s.io", Version: "v1beta1", Resource: "roles"}
+
+var rolesKind = schema.GroupVersionKind{Group: "rbac.authorization.k8s.io", Version: "v1beta1", Kind: "Role"}
+
+// Get takes name of the role, and returns the corresponding role object, and an error if there is any.
+func (c *FakeRoles) Get(name string, options v1.GetOptions) (result *v1beta1.Role, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(rolesResource, c.ns, name), &v1beta1.Role{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Role), err
+}
+
+// List takes label and field selectors, and returns the list of Roles that match those selectors.
+func (c *FakeRoles) List(opts v1.ListOptions) (result *v1beta1.RoleList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(rolesResource, rolesKind, c.ns, opts), &v1beta1.RoleList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta1.RoleList{ListMeta: obj.(*v1beta1.RoleList).ListMeta}
+ for _, item := range obj.(*v1beta1.RoleList).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 roles.
+func (c *FakeRoles) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(rolesResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a role and creates it. Returns the server's representation of the role, and an error, if there is any.
+func (c *FakeRoles) Create(role *v1beta1.Role) (result *v1beta1.Role, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(rolesResource, c.ns, role), &v1beta1.Role{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Role), err
+}
+
+// Update takes the representation of a role and updates it. Returns the server's representation of the role, and an error, if there is any.
+func (c *FakeRoles) Update(role *v1beta1.Role) (result *v1beta1.Role, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(rolesResource, c.ns, role), &v1beta1.Role{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Role), err
+}
+
+// Delete takes name of the role and deletes it. Returns an error if one occurs.
+func (c *FakeRoles) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(rolesResource, c.ns, name), &v1beta1.Role{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeRoles) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(rolesResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta1.RoleList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched role.
+func (c *FakeRoles) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.Role, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(rolesResource, c.ns, name, pt, data, subresources...), &v1beta1.Role{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.Role), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_rolebinding.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_rolebinding.go
new file mode 100644
index 000000000..06b93c93f
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_rolebinding.go
@@ -0,0 +1,128 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/api/rbac/v1beta1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeRoleBindings implements RoleBindingInterface
+type FakeRoleBindings struct {
+ Fake *FakeRbacV1beta1
+ ns string
+}
+
+var rolebindingsResource = schema.GroupVersionResource{Group: "rbac.authorization.k8s.io", Version: "v1beta1", Resource: "rolebindings"}
+
+var rolebindingsKind = schema.GroupVersionKind{Group: "rbac.authorization.k8s.io", Version: "v1beta1", Kind: "RoleBinding"}
+
+// Get takes name of the roleBinding, and returns the corresponding roleBinding object, and an error if there is any.
+func (c *FakeRoleBindings) Get(name string, options v1.GetOptions) (result *v1beta1.RoleBinding, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(rolebindingsResource, c.ns, name), &v1beta1.RoleBinding{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.RoleBinding), err
+}
+
+// List takes label and field selectors, and returns the list of RoleBindings that match those selectors.
+func (c *FakeRoleBindings) List(opts v1.ListOptions) (result *v1beta1.RoleBindingList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(rolebindingsResource, rolebindingsKind, c.ns, opts), &v1beta1.RoleBindingList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta1.RoleBindingList{ListMeta: obj.(*v1beta1.RoleBindingList).ListMeta}
+ for _, item := range obj.(*v1beta1.RoleBindingList).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 roleBindings.
+func (c *FakeRoleBindings) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(rolebindingsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a roleBinding and creates it. Returns the server's representation of the roleBinding, and an error, if there is any.
+func (c *FakeRoleBindings) Create(roleBinding *v1beta1.RoleBinding) (result *v1beta1.RoleBinding, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(rolebindingsResource, c.ns, roleBinding), &v1beta1.RoleBinding{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.RoleBinding), err
+}
+
+// Update takes the representation of a roleBinding and updates it. Returns the server's representation of the roleBinding, and an error, if there is any.
+func (c *FakeRoleBindings) Update(roleBinding *v1beta1.RoleBinding) (result *v1beta1.RoleBinding, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(rolebindingsResource, c.ns, roleBinding), &v1beta1.RoleBinding{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.RoleBinding), err
+}
+
+// Delete takes name of the roleBinding and deletes it. Returns an error if one occurs.
+func (c *FakeRoleBindings) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(rolebindingsResource, c.ns, name), &v1beta1.RoleBinding{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeRoleBindings) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(rolebindingsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta1.RoleBindingList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched roleBinding.
+func (c *FakeRoleBindings) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.RoleBinding, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(rolebindingsResource, c.ns, name, pt, data, subresources...), &v1beta1.RoleBinding{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.RoleBinding), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1/fake/fake_priorityclass.go b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1/fake/fake_priorityclass.go
new file mode 100644
index 000000000..60ad3a8db
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1/fake/fake_priorityclass.go
@@ -0,0 +1,120 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ schedulingv1 "k8s.io/api/scheduling/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakePriorityClasses implements PriorityClassInterface
+type FakePriorityClasses struct {
+ Fake *FakeSchedulingV1
+}
+
+var priorityclassesResource = schema.GroupVersionResource{Group: "scheduling.k8s.io", Version: "v1", Resource: "priorityclasses"}
+
+var priorityclassesKind = schema.GroupVersionKind{Group: "scheduling.k8s.io", Version: "v1", Kind: "PriorityClass"}
+
+// Get takes name of the priorityClass, and returns the corresponding priorityClass object, and an error if there is any.
+func (c *FakePriorityClasses) Get(name string, options v1.GetOptions) (result *schedulingv1.PriorityClass, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootGetAction(priorityclassesResource, name), &schedulingv1.PriorityClass{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*schedulingv1.PriorityClass), err
+}
+
+// List takes label and field selectors, and returns the list of PriorityClasses that match those selectors.
+func (c *FakePriorityClasses) List(opts v1.ListOptions) (result *schedulingv1.PriorityClassList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootListAction(priorityclassesResource, priorityclassesKind, opts), &schedulingv1.PriorityClassList{})
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &schedulingv1.PriorityClassList{ListMeta: obj.(*schedulingv1.PriorityClassList).ListMeta}
+ for _, item := range obj.(*schedulingv1.PriorityClassList).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 priorityClasses.
+func (c *FakePriorityClasses) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewRootWatchAction(priorityclassesResource, opts))
+}
+
+// Create takes the representation of a priorityClass and creates it. Returns the server's representation of the priorityClass, and an error, if there is any.
+func (c *FakePriorityClasses) Create(priorityClass *schedulingv1.PriorityClass) (result *schedulingv1.PriorityClass, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootCreateAction(priorityclassesResource, priorityClass), &schedulingv1.PriorityClass{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*schedulingv1.PriorityClass), err
+}
+
+// Update takes the representation of a priorityClass and updates it. Returns the server's representation of the priorityClass, and an error, if there is any.
+func (c *FakePriorityClasses) Update(priorityClass *schedulingv1.PriorityClass) (result *schedulingv1.PriorityClass, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateAction(priorityclassesResource, priorityClass), &schedulingv1.PriorityClass{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*schedulingv1.PriorityClass), err
+}
+
+// Delete takes name of the priorityClass and deletes it. Returns an error if one occurs.
+func (c *FakePriorityClasses) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewRootDeleteAction(priorityclassesResource, name), &schedulingv1.PriorityClass{})
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakePriorityClasses) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewRootDeleteCollectionAction(priorityclassesResource, listOptions)
+
+ _, err := c.Fake.Invokes(action, &schedulingv1.PriorityClassList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched priorityClass.
+func (c *FakePriorityClasses) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *schedulingv1.PriorityClass, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootPatchSubresourceAction(priorityclassesResource, name, pt, data, subresources...), &schedulingv1.PriorityClass{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*schedulingv1.PriorityClass), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1/fake/fake_scheduling_client.go b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1/fake/fake_scheduling_client.go
new file mode 100644
index 000000000..a64ac945b
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1/fake/fake_scheduling_client.go
@@ -0,0 +1,40 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1 "k8s.io/client-go/kubernetes/typed/scheduling/v1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeSchedulingV1 struct {
+ *testing.Fake
+}
+
+func (c *FakeSchedulingV1) PriorityClasses() v1.PriorityClassInterface {
+ return &FakePriorityClasses{c}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeSchedulingV1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/fake_priorityclass.go b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/fake_priorityclass.go
new file mode 100644
index 000000000..e592ed137
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/fake_priorityclass.go
@@ -0,0 +1,120 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1alpha1 "k8s.io/api/scheduling/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakePriorityClasses implements PriorityClassInterface
+type FakePriorityClasses struct {
+ Fake *FakeSchedulingV1alpha1
+}
+
+var priorityclassesResource = schema.GroupVersionResource{Group: "scheduling.k8s.io", Version: "v1alpha1", Resource: "priorityclasses"}
+
+var priorityclassesKind = schema.GroupVersionKind{Group: "scheduling.k8s.io", Version: "v1alpha1", Kind: "PriorityClass"}
+
+// Get takes name of the priorityClass, and returns the corresponding priorityClass object, and an error if there is any.
+func (c *FakePriorityClasses) Get(name string, options v1.GetOptions) (result *v1alpha1.PriorityClass, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootGetAction(priorityclassesResource, name), &v1alpha1.PriorityClass{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.PriorityClass), err
+}
+
+// List takes label and field selectors, and returns the list of PriorityClasses that match those selectors.
+func (c *FakePriorityClasses) List(opts v1.ListOptions) (result *v1alpha1.PriorityClassList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootListAction(priorityclassesResource, priorityclassesKind, opts), &v1alpha1.PriorityClassList{})
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1alpha1.PriorityClassList{ListMeta: obj.(*v1alpha1.PriorityClassList).ListMeta}
+ for _, item := range obj.(*v1alpha1.PriorityClassList).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 priorityClasses.
+func (c *FakePriorityClasses) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewRootWatchAction(priorityclassesResource, opts))
+}
+
+// Create takes the representation of a priorityClass and creates it. Returns the server's representation of the priorityClass, and an error, if there is any.
+func (c *FakePriorityClasses) Create(priorityClass *v1alpha1.PriorityClass) (result *v1alpha1.PriorityClass, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootCreateAction(priorityclassesResource, priorityClass), &v1alpha1.PriorityClass{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.PriorityClass), err
+}
+
+// Update takes the representation of a priorityClass and updates it. Returns the server's representation of the priorityClass, and an error, if there is any.
+func (c *FakePriorityClasses) Update(priorityClass *v1alpha1.PriorityClass) (result *v1alpha1.PriorityClass, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateAction(priorityclassesResource, priorityClass), &v1alpha1.PriorityClass{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.PriorityClass), err
+}
+
+// Delete takes name of the priorityClass and deletes it. Returns an error if one occurs.
+func (c *FakePriorityClasses) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewRootDeleteAction(priorityclassesResource, name), &v1alpha1.PriorityClass{})
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakePriorityClasses) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewRootDeleteCollectionAction(priorityclassesResource, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1alpha1.PriorityClassList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched priorityClass.
+func (c *FakePriorityClasses) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.PriorityClass, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootPatchSubresourceAction(priorityclassesResource, name, pt, data, subresources...), &v1alpha1.PriorityClass{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.PriorityClass), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/fake_scheduling_client.go b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/fake_scheduling_client.go
new file mode 100644
index 000000000..974ba193f
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/fake_scheduling_client.go
@@ -0,0 +1,40 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1alpha1 "k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeSchedulingV1alpha1 struct {
+ *testing.Fake
+}
+
+func (c *FakeSchedulingV1alpha1) PriorityClasses() v1alpha1.PriorityClassInterface {
+ return &FakePriorityClasses{c}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeSchedulingV1alpha1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake/fake_priorityclass.go b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake/fake_priorityclass.go
new file mode 100644
index 000000000..44ce64b5c
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake/fake_priorityclass.go
@@ -0,0 +1,120 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/api/scheduling/v1beta1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakePriorityClasses implements PriorityClassInterface
+type FakePriorityClasses struct {
+ Fake *FakeSchedulingV1beta1
+}
+
+var priorityclassesResource = schema.GroupVersionResource{Group: "scheduling.k8s.io", Version: "v1beta1", Resource: "priorityclasses"}
+
+var priorityclassesKind = schema.GroupVersionKind{Group: "scheduling.k8s.io", Version: "v1beta1", Kind: "PriorityClass"}
+
+// Get takes name of the priorityClass, and returns the corresponding priorityClass object, and an error if there is any.
+func (c *FakePriorityClasses) Get(name string, options v1.GetOptions) (result *v1beta1.PriorityClass, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootGetAction(priorityclassesResource, name), &v1beta1.PriorityClass{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.PriorityClass), err
+}
+
+// List takes label and field selectors, and returns the list of PriorityClasses that match those selectors.
+func (c *FakePriorityClasses) List(opts v1.ListOptions) (result *v1beta1.PriorityClassList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootListAction(priorityclassesResource, priorityclassesKind, opts), &v1beta1.PriorityClassList{})
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta1.PriorityClassList{ListMeta: obj.(*v1beta1.PriorityClassList).ListMeta}
+ for _, item := range obj.(*v1beta1.PriorityClassList).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 priorityClasses.
+func (c *FakePriorityClasses) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewRootWatchAction(priorityclassesResource, opts))
+}
+
+// Create takes the representation of a priorityClass and creates it. Returns the server's representation of the priorityClass, and an error, if there is any.
+func (c *FakePriorityClasses) Create(priorityClass *v1beta1.PriorityClass) (result *v1beta1.PriorityClass, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootCreateAction(priorityclassesResource, priorityClass), &v1beta1.PriorityClass{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.PriorityClass), err
+}
+
+// Update takes the representation of a priorityClass and updates it. Returns the server's representation of the priorityClass, and an error, if there is any.
+func (c *FakePriorityClasses) Update(priorityClass *v1beta1.PriorityClass) (result *v1beta1.PriorityClass, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateAction(priorityclassesResource, priorityClass), &v1beta1.PriorityClass{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.PriorityClass), err
+}
+
+// Delete takes name of the priorityClass and deletes it. Returns an error if one occurs.
+func (c *FakePriorityClasses) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewRootDeleteAction(priorityclassesResource, name), &v1beta1.PriorityClass{})
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakePriorityClasses) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewRootDeleteCollectionAction(priorityclassesResource, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta1.PriorityClassList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched priorityClass.
+func (c *FakePriorityClasses) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.PriorityClass, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootPatchSubresourceAction(priorityclassesResource, name, pt, data, subresources...), &v1beta1.PriorityClass{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.PriorityClass), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake/fake_scheduling_client.go b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake/fake_scheduling_client.go
new file mode 100644
index 000000000..4a6878a45
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake/fake_scheduling_client.go
@@ -0,0 +1,40 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeSchedulingV1beta1 struct {
+ *testing.Fake
+}
+
+func (c *FakeSchedulingV1beta1) PriorityClasses() v1beta1.PriorityClassInterface {
+ return &FakePriorityClasses{c}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeSchedulingV1beta1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/fake_podpreset.go b/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/fake_podpreset.go
new file mode 100644
index 000000000..273a027fa
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/fake_podpreset.go
@@ -0,0 +1,128 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1alpha1 "k8s.io/api/settings/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakePodPresets implements PodPresetInterface
+type FakePodPresets struct {
+ Fake *FakeSettingsV1alpha1
+ ns string
+}
+
+var podpresetsResource = schema.GroupVersionResource{Group: "settings.k8s.io", Version: "v1alpha1", Resource: "podpresets"}
+
+var podpresetsKind = schema.GroupVersionKind{Group: "settings.k8s.io", Version: "v1alpha1", Kind: "PodPreset"}
+
+// Get takes name of the podPreset, and returns the corresponding podPreset object, and an error if there is any.
+func (c *FakePodPresets) Get(name string, options v1.GetOptions) (result *v1alpha1.PodPreset, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(podpresetsResource, c.ns, name), &v1alpha1.PodPreset{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.PodPreset), err
+}
+
+// List takes label and field selectors, and returns the list of PodPresets that match those selectors.
+func (c *FakePodPresets) List(opts v1.ListOptions) (result *v1alpha1.PodPresetList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(podpresetsResource, podpresetsKind, c.ns, opts), &v1alpha1.PodPresetList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1alpha1.PodPresetList{ListMeta: obj.(*v1alpha1.PodPresetList).ListMeta}
+ for _, item := range obj.(*v1alpha1.PodPresetList).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 podPresets.
+func (c *FakePodPresets) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(podpresetsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a podPreset and creates it. Returns the server's representation of the podPreset, and an error, if there is any.
+func (c *FakePodPresets) Create(podPreset *v1alpha1.PodPreset) (result *v1alpha1.PodPreset, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(podpresetsResource, c.ns, podPreset), &v1alpha1.PodPreset{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.PodPreset), err
+}
+
+// Update takes the representation of a podPreset and updates it. Returns the server's representation of the podPreset, and an error, if there is any.
+func (c *FakePodPresets) Update(podPreset *v1alpha1.PodPreset) (result *v1alpha1.PodPreset, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(podpresetsResource, c.ns, podPreset), &v1alpha1.PodPreset{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.PodPreset), err
+}
+
+// Delete takes name of the podPreset and deletes it. Returns an error if one occurs.
+func (c *FakePodPresets) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(podpresetsResource, c.ns, name), &v1alpha1.PodPreset{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakePodPresets) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(podpresetsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1alpha1.PodPresetList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched podPreset.
+func (c *FakePodPresets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.PodPreset, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(podpresetsResource, c.ns, name, pt, data, subresources...), &v1alpha1.PodPreset{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.PodPreset), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/fake_settings_client.go b/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/fake_settings_client.go
new file mode 100644
index 000000000..a142edfed
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/fake_settings_client.go
@@ -0,0 +1,40 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1alpha1 "k8s.io/client-go/kubernetes/typed/settings/v1alpha1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeSettingsV1alpha1 struct {
+ *testing.Fake
+}
+
+func (c *FakeSettingsV1alpha1) PodPresets(namespace string) v1alpha1.PodPresetInterface {
+ return &FakePodPresets{c, namespace}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeSettingsV1alpha1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/fake/fake_storage_client.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/fake/fake_storage_client.go
new file mode 100644
index 000000000..967a52850
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/fake/fake_storage_client.go
@@ -0,0 +1,44 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1 "k8s.io/client-go/kubernetes/typed/storage/v1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeStorageV1 struct {
+ *testing.Fake
+}
+
+func (c *FakeStorageV1) StorageClasses() v1.StorageClassInterface {
+ return &FakeStorageClasses{c}
+}
+
+func (c *FakeStorageV1) VolumeAttachments() v1.VolumeAttachmentInterface {
+ return &FakeVolumeAttachments{c}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeStorageV1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/fake/fake_storageclass.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/fake/fake_storageclass.go
new file mode 100644
index 000000000..c7531d879
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/fake/fake_storageclass.go
@@ -0,0 +1,120 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ storagev1 "k8s.io/api/storage/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeStorageClasses implements StorageClassInterface
+type FakeStorageClasses struct {
+ Fake *FakeStorageV1
+}
+
+var storageclassesResource = schema.GroupVersionResource{Group: "storage.k8s.io", Version: "v1", Resource: "storageclasses"}
+
+var storageclassesKind = schema.GroupVersionKind{Group: "storage.k8s.io", Version: "v1", Kind: "StorageClass"}
+
+// Get takes name of the storageClass, and returns the corresponding storageClass object, and an error if there is any.
+func (c *FakeStorageClasses) Get(name string, options v1.GetOptions) (result *storagev1.StorageClass, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootGetAction(storageclassesResource, name), &storagev1.StorageClass{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*storagev1.StorageClass), err
+}
+
+// List takes label and field selectors, and returns the list of StorageClasses that match those selectors.
+func (c *FakeStorageClasses) List(opts v1.ListOptions) (result *storagev1.StorageClassList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootListAction(storageclassesResource, storageclassesKind, opts), &storagev1.StorageClassList{})
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &storagev1.StorageClassList{ListMeta: obj.(*storagev1.StorageClassList).ListMeta}
+ for _, item := range obj.(*storagev1.StorageClassList).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 storageClasses.
+func (c *FakeStorageClasses) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewRootWatchAction(storageclassesResource, opts))
+}
+
+// Create takes the representation of a storageClass and creates it. Returns the server's representation of the storageClass, and an error, if there is any.
+func (c *FakeStorageClasses) Create(storageClass *storagev1.StorageClass) (result *storagev1.StorageClass, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootCreateAction(storageclassesResource, storageClass), &storagev1.StorageClass{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*storagev1.StorageClass), err
+}
+
+// Update takes the representation of a storageClass and updates it. Returns the server's representation of the storageClass, and an error, if there is any.
+func (c *FakeStorageClasses) Update(storageClass *storagev1.StorageClass) (result *storagev1.StorageClass, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateAction(storageclassesResource, storageClass), &storagev1.StorageClass{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*storagev1.StorageClass), err
+}
+
+// Delete takes name of the storageClass and deletes it. Returns an error if one occurs.
+func (c *FakeStorageClasses) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewRootDeleteAction(storageclassesResource, name), &storagev1.StorageClass{})
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeStorageClasses) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewRootDeleteCollectionAction(storageclassesResource, listOptions)
+
+ _, err := c.Fake.Invokes(action, &storagev1.StorageClassList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched storageClass.
+func (c *FakeStorageClasses) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *storagev1.StorageClass, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootPatchSubresourceAction(storageclassesResource, name, pt, data, subresources...), &storagev1.StorageClass{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*storagev1.StorageClass), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/fake/fake_volumeattachment.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/fake/fake_volumeattachment.go
new file mode 100644
index 000000000..58e09da46
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/fake/fake_volumeattachment.go
@@ -0,0 +1,131 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ storagev1 "k8s.io/api/storage/v1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeVolumeAttachments implements VolumeAttachmentInterface
+type FakeVolumeAttachments struct {
+ Fake *FakeStorageV1
+}
+
+var volumeattachmentsResource = schema.GroupVersionResource{Group: "storage.k8s.io", Version: "v1", Resource: "volumeattachments"}
+
+var volumeattachmentsKind = schema.GroupVersionKind{Group: "storage.k8s.io", Version: "v1", Kind: "VolumeAttachment"}
+
+// Get takes name of the volumeAttachment, and returns the corresponding volumeAttachment object, and an error if there is any.
+func (c *FakeVolumeAttachments) Get(name string, options v1.GetOptions) (result *storagev1.VolumeAttachment, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootGetAction(volumeattachmentsResource, name), &storagev1.VolumeAttachment{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*storagev1.VolumeAttachment), err
+}
+
+// List takes label and field selectors, and returns the list of VolumeAttachments that match those selectors.
+func (c *FakeVolumeAttachments) List(opts v1.ListOptions) (result *storagev1.VolumeAttachmentList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootListAction(volumeattachmentsResource, volumeattachmentsKind, opts), &storagev1.VolumeAttachmentList{})
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &storagev1.VolumeAttachmentList{ListMeta: obj.(*storagev1.VolumeAttachmentList).ListMeta}
+ for _, item := range obj.(*storagev1.VolumeAttachmentList).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 volumeAttachments.
+func (c *FakeVolumeAttachments) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewRootWatchAction(volumeattachmentsResource, opts))
+}
+
+// Create takes the representation of a volumeAttachment and creates it. Returns the server's representation of the volumeAttachment, and an error, if there is any.
+func (c *FakeVolumeAttachments) Create(volumeAttachment *storagev1.VolumeAttachment) (result *storagev1.VolumeAttachment, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootCreateAction(volumeattachmentsResource, volumeAttachment), &storagev1.VolumeAttachment{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*storagev1.VolumeAttachment), err
+}
+
+// Update takes the representation of a volumeAttachment and updates it. Returns the server's representation of the volumeAttachment, and an error, if there is any.
+func (c *FakeVolumeAttachments) Update(volumeAttachment *storagev1.VolumeAttachment) (result *storagev1.VolumeAttachment, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateAction(volumeattachmentsResource, volumeAttachment), &storagev1.VolumeAttachment{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*storagev1.VolumeAttachment), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeVolumeAttachments) UpdateStatus(volumeAttachment *storagev1.VolumeAttachment) (*storagev1.VolumeAttachment, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateSubresourceAction(volumeattachmentsResource, "status", volumeAttachment), &storagev1.VolumeAttachment{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*storagev1.VolumeAttachment), err
+}
+
+// Delete takes name of the volumeAttachment and deletes it. Returns an error if one occurs.
+func (c *FakeVolumeAttachments) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewRootDeleteAction(volumeattachmentsResource, name), &storagev1.VolumeAttachment{})
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeVolumeAttachments) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewRootDeleteCollectionAction(volumeattachmentsResource, listOptions)
+
+ _, err := c.Fake.Invokes(action, &storagev1.VolumeAttachmentList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched volumeAttachment.
+func (c *FakeVolumeAttachments) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *storagev1.VolumeAttachment, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootPatchSubresourceAction(volumeattachmentsResource, name, pt, data, subresources...), &storagev1.VolumeAttachment{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*storagev1.VolumeAttachment), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/fake_storage_client.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/fake_storage_client.go
new file mode 100644
index 000000000..1a4d9f56f
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/fake_storage_client.go
@@ -0,0 +1,40 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1alpha1 "k8s.io/client-go/kubernetes/typed/storage/v1alpha1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeStorageV1alpha1 struct {
+ *testing.Fake
+}
+
+func (c *FakeStorageV1alpha1) VolumeAttachments() v1alpha1.VolumeAttachmentInterface {
+ return &FakeVolumeAttachments{c}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeStorageV1alpha1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/fake_volumeattachment.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/fake_volumeattachment.go
new file mode 100644
index 000000000..86f53e2d4
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/fake_volumeattachment.go
@@ -0,0 +1,131 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1alpha1 "k8s.io/api/storage/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeVolumeAttachments implements VolumeAttachmentInterface
+type FakeVolumeAttachments struct {
+ Fake *FakeStorageV1alpha1
+}
+
+var volumeattachmentsResource = schema.GroupVersionResource{Group: "storage.k8s.io", Version: "v1alpha1", Resource: "volumeattachments"}
+
+var volumeattachmentsKind = schema.GroupVersionKind{Group: "storage.k8s.io", Version: "v1alpha1", Kind: "VolumeAttachment"}
+
+// Get takes name of the volumeAttachment, and returns the corresponding volumeAttachment object, and an error if there is any.
+func (c *FakeVolumeAttachments) Get(name string, options v1.GetOptions) (result *v1alpha1.VolumeAttachment, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootGetAction(volumeattachmentsResource, name), &v1alpha1.VolumeAttachment{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.VolumeAttachment), err
+}
+
+// List takes label and field selectors, and returns the list of VolumeAttachments that match those selectors.
+func (c *FakeVolumeAttachments) List(opts v1.ListOptions) (result *v1alpha1.VolumeAttachmentList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootListAction(volumeattachmentsResource, volumeattachmentsKind, opts), &v1alpha1.VolumeAttachmentList{})
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1alpha1.VolumeAttachmentList{ListMeta: obj.(*v1alpha1.VolumeAttachmentList).ListMeta}
+ for _, item := range obj.(*v1alpha1.VolumeAttachmentList).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 volumeAttachments.
+func (c *FakeVolumeAttachments) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewRootWatchAction(volumeattachmentsResource, opts))
+}
+
+// Create takes the representation of a volumeAttachment and creates it. Returns the server's representation of the volumeAttachment, and an error, if there is any.
+func (c *FakeVolumeAttachments) Create(volumeAttachment *v1alpha1.VolumeAttachment) (result *v1alpha1.VolumeAttachment, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootCreateAction(volumeattachmentsResource, volumeAttachment), &v1alpha1.VolumeAttachment{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.VolumeAttachment), err
+}
+
+// Update takes the representation of a volumeAttachment and updates it. Returns the server's representation of the volumeAttachment, and an error, if there is any.
+func (c *FakeVolumeAttachments) Update(volumeAttachment *v1alpha1.VolumeAttachment) (result *v1alpha1.VolumeAttachment, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateAction(volumeattachmentsResource, volumeAttachment), &v1alpha1.VolumeAttachment{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.VolumeAttachment), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeVolumeAttachments) UpdateStatus(volumeAttachment *v1alpha1.VolumeAttachment) (*v1alpha1.VolumeAttachment, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateSubresourceAction(volumeattachmentsResource, "status", volumeAttachment), &v1alpha1.VolumeAttachment{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.VolumeAttachment), err
+}
+
+// Delete takes name of the volumeAttachment and deletes it. Returns an error if one occurs.
+func (c *FakeVolumeAttachments) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewRootDeleteAction(volumeattachmentsResource, name), &v1alpha1.VolumeAttachment{})
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeVolumeAttachments) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewRootDeleteCollectionAction(volumeattachmentsResource, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1alpha1.VolumeAttachmentList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched volumeAttachment.
+func (c *FakeVolumeAttachments) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.VolumeAttachment, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootPatchSubresourceAction(volumeattachmentsResource, name, pt, data, subresources...), &v1alpha1.VolumeAttachment{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.VolumeAttachment), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_csidriver.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_csidriver.go
new file mode 100644
index 000000000..2446316b2
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_csidriver.go
@@ -0,0 +1,120 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/api/storage/v1beta1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeCSIDrivers implements CSIDriverInterface
+type FakeCSIDrivers struct {
+ Fake *FakeStorageV1beta1
+}
+
+var csidriversResource = schema.GroupVersionResource{Group: "storage.k8s.io", Version: "v1beta1", Resource: "csidrivers"}
+
+var csidriversKind = schema.GroupVersionKind{Group: "storage.k8s.io", Version: "v1beta1", Kind: "CSIDriver"}
+
+// Get takes name of the cSIDriver, and returns the corresponding cSIDriver object, and an error if there is any.
+func (c *FakeCSIDrivers) Get(name string, options v1.GetOptions) (result *v1beta1.CSIDriver, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootGetAction(csidriversResource, name), &v1beta1.CSIDriver{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.CSIDriver), err
+}
+
+// List takes label and field selectors, and returns the list of CSIDrivers that match those selectors.
+func (c *FakeCSIDrivers) List(opts v1.ListOptions) (result *v1beta1.CSIDriverList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootListAction(csidriversResource, csidriversKind, opts), &v1beta1.CSIDriverList{})
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta1.CSIDriverList{ListMeta: obj.(*v1beta1.CSIDriverList).ListMeta}
+ for _, item := range obj.(*v1beta1.CSIDriverList).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 cSIDrivers.
+func (c *FakeCSIDrivers) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewRootWatchAction(csidriversResource, opts))
+}
+
+// Create takes the representation of a cSIDriver and creates it. Returns the server's representation of the cSIDriver, and an error, if there is any.
+func (c *FakeCSIDrivers) Create(cSIDriver *v1beta1.CSIDriver) (result *v1beta1.CSIDriver, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootCreateAction(csidriversResource, cSIDriver), &v1beta1.CSIDriver{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.CSIDriver), err
+}
+
+// Update takes the representation of a cSIDriver and updates it. Returns the server's representation of the cSIDriver, and an error, if there is any.
+func (c *FakeCSIDrivers) Update(cSIDriver *v1beta1.CSIDriver) (result *v1beta1.CSIDriver, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateAction(csidriversResource, cSIDriver), &v1beta1.CSIDriver{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.CSIDriver), err
+}
+
+// Delete takes name of the cSIDriver and deletes it. Returns an error if one occurs.
+func (c *FakeCSIDrivers) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewRootDeleteAction(csidriversResource, name), &v1beta1.CSIDriver{})
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeCSIDrivers) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewRootDeleteCollectionAction(csidriversResource, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta1.CSIDriverList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched cSIDriver.
+func (c *FakeCSIDrivers) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.CSIDriver, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootPatchSubresourceAction(csidriversResource, name, pt, data, subresources...), &v1beta1.CSIDriver{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.CSIDriver), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_csinode.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_csinode.go
new file mode 100644
index 000000000..0050f4743
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_csinode.go
@@ -0,0 +1,120 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/api/storage/v1beta1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeCSINodes implements CSINodeInterface
+type FakeCSINodes struct {
+ Fake *FakeStorageV1beta1
+}
+
+var csinodesResource = schema.GroupVersionResource{Group: "storage.k8s.io", Version: "v1beta1", Resource: "csinodes"}
+
+var csinodesKind = schema.GroupVersionKind{Group: "storage.k8s.io", Version: "v1beta1", Kind: "CSINode"}
+
+// Get takes name of the cSINode, and returns the corresponding cSINode object, and an error if there is any.
+func (c *FakeCSINodes) Get(name string, options v1.GetOptions) (result *v1beta1.CSINode, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootGetAction(csinodesResource, name), &v1beta1.CSINode{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.CSINode), err
+}
+
+// List takes label and field selectors, and returns the list of CSINodes that match those selectors.
+func (c *FakeCSINodes) List(opts v1.ListOptions) (result *v1beta1.CSINodeList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootListAction(csinodesResource, csinodesKind, opts), &v1beta1.CSINodeList{})
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta1.CSINodeList{ListMeta: obj.(*v1beta1.CSINodeList).ListMeta}
+ for _, item := range obj.(*v1beta1.CSINodeList).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 cSINodes.
+func (c *FakeCSINodes) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewRootWatchAction(csinodesResource, opts))
+}
+
+// Create takes the representation of a cSINode and creates it. Returns the server's representation of the cSINode, and an error, if there is any.
+func (c *FakeCSINodes) Create(cSINode *v1beta1.CSINode) (result *v1beta1.CSINode, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootCreateAction(csinodesResource, cSINode), &v1beta1.CSINode{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.CSINode), err
+}
+
+// Update takes the representation of a cSINode and updates it. Returns the server's representation of the cSINode, and an error, if there is any.
+func (c *FakeCSINodes) Update(cSINode *v1beta1.CSINode) (result *v1beta1.CSINode, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateAction(csinodesResource, cSINode), &v1beta1.CSINode{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.CSINode), err
+}
+
+// Delete takes name of the cSINode and deletes it. Returns an error if one occurs.
+func (c *FakeCSINodes) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewRootDeleteAction(csinodesResource, name), &v1beta1.CSINode{})
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeCSINodes) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewRootDeleteCollectionAction(csinodesResource, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta1.CSINodeList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched cSINode.
+func (c *FakeCSINodes) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.CSINode, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootPatchSubresourceAction(csinodesResource, name, pt, data, subresources...), &v1beta1.CSINode{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.CSINode), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_storage_client.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_storage_client.go
new file mode 100644
index 000000000..7968c9003
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_storage_client.go
@@ -0,0 +1,52 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/client-go/kubernetes/typed/storage/v1beta1"
+ rest "k8s.io/client-go/rest"
+ testing "k8s.io/client-go/testing"
+)
+
+type FakeStorageV1beta1 struct {
+ *testing.Fake
+}
+
+func (c *FakeStorageV1beta1) CSIDrivers() v1beta1.CSIDriverInterface {
+ return &FakeCSIDrivers{c}
+}
+
+func (c *FakeStorageV1beta1) CSINodes() v1beta1.CSINodeInterface {
+ return &FakeCSINodes{c}
+}
+
+func (c *FakeStorageV1beta1) StorageClasses() v1beta1.StorageClassInterface {
+ return &FakeStorageClasses{c}
+}
+
+func (c *FakeStorageV1beta1) VolumeAttachments() v1beta1.VolumeAttachmentInterface {
+ return &FakeVolumeAttachments{c}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeStorageV1beta1) RESTClient() rest.Interface {
+ var ret *rest.RESTClient
+ return ret
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_storageclass.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_storageclass.go
new file mode 100644
index 000000000..9fc8ca991
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_storageclass.go
@@ -0,0 +1,120 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/api/storage/v1beta1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeStorageClasses implements StorageClassInterface
+type FakeStorageClasses struct {
+ Fake *FakeStorageV1beta1
+}
+
+var storageclassesResource = schema.GroupVersionResource{Group: "storage.k8s.io", Version: "v1beta1", Resource: "storageclasses"}
+
+var storageclassesKind = schema.GroupVersionKind{Group: "storage.k8s.io", Version: "v1beta1", Kind: "StorageClass"}
+
+// Get takes name of the storageClass, and returns the corresponding storageClass object, and an error if there is any.
+func (c *FakeStorageClasses) Get(name string, options v1.GetOptions) (result *v1beta1.StorageClass, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootGetAction(storageclassesResource, name), &v1beta1.StorageClass{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.StorageClass), err
+}
+
+// List takes label and field selectors, and returns the list of StorageClasses that match those selectors.
+func (c *FakeStorageClasses) List(opts v1.ListOptions) (result *v1beta1.StorageClassList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootListAction(storageclassesResource, storageclassesKind, opts), &v1beta1.StorageClassList{})
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta1.StorageClassList{ListMeta: obj.(*v1beta1.StorageClassList).ListMeta}
+ for _, item := range obj.(*v1beta1.StorageClassList).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 storageClasses.
+func (c *FakeStorageClasses) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewRootWatchAction(storageclassesResource, opts))
+}
+
+// Create takes the representation of a storageClass and creates it. Returns the server's representation of the storageClass, and an error, if there is any.
+func (c *FakeStorageClasses) Create(storageClass *v1beta1.StorageClass) (result *v1beta1.StorageClass, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootCreateAction(storageclassesResource, storageClass), &v1beta1.StorageClass{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.StorageClass), err
+}
+
+// Update takes the representation of a storageClass and updates it. Returns the server's representation of the storageClass, and an error, if there is any.
+func (c *FakeStorageClasses) Update(storageClass *v1beta1.StorageClass) (result *v1beta1.StorageClass, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateAction(storageclassesResource, storageClass), &v1beta1.StorageClass{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.StorageClass), err
+}
+
+// Delete takes name of the storageClass and deletes it. Returns an error if one occurs.
+func (c *FakeStorageClasses) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewRootDeleteAction(storageclassesResource, name), &v1beta1.StorageClass{})
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeStorageClasses) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewRootDeleteCollectionAction(storageclassesResource, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta1.StorageClassList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched storageClass.
+func (c *FakeStorageClasses) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.StorageClass, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootPatchSubresourceAction(storageclassesResource, name, pt, data, subresources...), &v1beta1.StorageClass{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.StorageClass), err
+}
diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_volumeattachment.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_volumeattachment.go
new file mode 100644
index 000000000..043098f45
--- /dev/null
+++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_volumeattachment.go
@@ -0,0 +1,131 @@
+/*
+Copyright 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1beta1 "k8s.io/api/storage/v1beta1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeVolumeAttachments implements VolumeAttachmentInterface
+type FakeVolumeAttachments struct {
+ Fake *FakeStorageV1beta1
+}
+
+var volumeattachmentsResource = schema.GroupVersionResource{Group: "storage.k8s.io", Version: "v1beta1", Resource: "volumeattachments"}
+
+var volumeattachmentsKind = schema.GroupVersionKind{Group: "storage.k8s.io", Version: "v1beta1", Kind: "VolumeAttachment"}
+
+// Get takes name of the volumeAttachment, and returns the corresponding volumeAttachment object, and an error if there is any.
+func (c *FakeVolumeAttachments) Get(name string, options v1.GetOptions) (result *v1beta1.VolumeAttachment, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootGetAction(volumeattachmentsResource, name), &v1beta1.VolumeAttachment{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.VolumeAttachment), err
+}
+
+// List takes label and field selectors, and returns the list of VolumeAttachments that match those selectors.
+func (c *FakeVolumeAttachments) List(opts v1.ListOptions) (result *v1beta1.VolumeAttachmentList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootListAction(volumeattachmentsResource, volumeattachmentsKind, opts), &v1beta1.VolumeAttachmentList{})
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1beta1.VolumeAttachmentList{ListMeta: obj.(*v1beta1.VolumeAttachmentList).ListMeta}
+ for _, item := range obj.(*v1beta1.VolumeAttachmentList).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 volumeAttachments.
+func (c *FakeVolumeAttachments) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewRootWatchAction(volumeattachmentsResource, opts))
+}
+
+// Create takes the representation of a volumeAttachment and creates it. Returns the server's representation of the volumeAttachment, and an error, if there is any.
+func (c *FakeVolumeAttachments) Create(volumeAttachment *v1beta1.VolumeAttachment) (result *v1beta1.VolumeAttachment, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootCreateAction(volumeattachmentsResource, volumeAttachment), &v1beta1.VolumeAttachment{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.VolumeAttachment), err
+}
+
+// Update takes the representation of a volumeAttachment and updates it. Returns the server's representation of the volumeAttachment, and an error, if there is any.
+func (c *FakeVolumeAttachments) Update(volumeAttachment *v1beta1.VolumeAttachment) (result *v1beta1.VolumeAttachment, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateAction(volumeattachmentsResource, volumeAttachment), &v1beta1.VolumeAttachment{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.VolumeAttachment), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeVolumeAttachments) UpdateStatus(volumeAttachment *v1beta1.VolumeAttachment) (*v1beta1.VolumeAttachment, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootUpdateSubresourceAction(volumeattachmentsResource, "status", volumeAttachment), &v1beta1.VolumeAttachment{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.VolumeAttachment), err
+}
+
+// Delete takes name of the volumeAttachment and deletes it. Returns an error if one occurs.
+func (c *FakeVolumeAttachments) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewRootDeleteAction(volumeattachmentsResource, name), &v1beta1.VolumeAttachment{})
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeVolumeAttachments) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewRootDeleteCollectionAction(volumeattachmentsResource, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1beta1.VolumeAttachmentList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched volumeAttachment.
+func (c *FakeVolumeAttachments) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.VolumeAttachment, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootPatchSubresourceAction(volumeattachmentsResource, name, pt, data, subresources...), &v1beta1.VolumeAttachment{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1beta1.VolumeAttachment), err
+}
diff --git a/vendor/k8s.io/client-go/testing/actions.go b/vendor/k8s.io/client-go/testing/actions.go
new file mode 100644
index 000000000..e6db578ed
--- /dev/null
+++ b/vendor/k8s.io/client-go/testing/actions.go
@@ -0,0 +1,671 @@
+/*
+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 testing
+
+import (
+ "fmt"
+ "path"
+ "strings"
+
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/fields"
+ "k8s.io/apimachinery/pkg/labels"
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/apimachinery/pkg/types"
+)
+
+func NewRootGetAction(resource schema.GroupVersionResource, name string) GetActionImpl {
+ action := GetActionImpl{}
+ action.Verb = "get"
+ action.Resource = resource
+ action.Name = name
+
+ return action
+}
+
+func NewGetAction(resource schema.GroupVersionResource, namespace, name string) GetActionImpl {
+ action := GetActionImpl{}
+ action.Verb = "get"
+ action.Resource = resource
+ action.Namespace = namespace
+ action.Name = name
+
+ return action
+}
+
+func NewGetSubresourceAction(resource schema.GroupVersionResource, namespace, subresource, name string) GetActionImpl {
+ action := GetActionImpl{}
+ action.Verb = "get"
+ action.Resource = resource
+ action.Subresource = subresource
+ action.Namespace = namespace
+ action.Name = name
+
+ return action
+}
+
+func NewRootGetSubresourceAction(resource schema.GroupVersionResource, subresource, name string) GetActionImpl {
+ action := GetActionImpl{}
+ action.Verb = "get"
+ action.Resource = resource
+ action.Subresource = subresource
+ action.Name = name
+
+ return action
+}
+
+func NewRootListAction(resource schema.GroupVersionResource, kind schema.GroupVersionKind, opts interface{}) ListActionImpl {
+ action := ListActionImpl{}
+ action.Verb = "list"
+ action.Resource = resource
+ action.Kind = kind
+ labelSelector, fieldSelector, _ := ExtractFromListOptions(opts)
+ action.ListRestrictions = ListRestrictions{labelSelector, fieldSelector}
+
+ return action
+}
+
+func NewListAction(resource schema.GroupVersionResource, kind schema.GroupVersionKind, namespace string, opts interface{}) ListActionImpl {
+ action := ListActionImpl{}
+ action.Verb = "list"
+ action.Resource = resource
+ action.Kind = kind
+ action.Namespace = namespace
+ labelSelector, fieldSelector, _ := ExtractFromListOptions(opts)
+ action.ListRestrictions = ListRestrictions{labelSelector, fieldSelector}
+
+ return action
+}
+
+func NewRootCreateAction(resource schema.GroupVersionResource, object runtime.Object) CreateActionImpl {
+ action := CreateActionImpl{}
+ action.Verb = "create"
+ action.Resource = resource
+ action.Object = object
+
+ return action
+}
+
+func NewCreateAction(resource schema.GroupVersionResource, namespace string, object runtime.Object) CreateActionImpl {
+ action := CreateActionImpl{}
+ action.Verb = "create"
+ action.Resource = resource
+ action.Namespace = namespace
+ action.Object = object
+
+ return action
+}
+
+func NewRootCreateSubresourceAction(resource schema.GroupVersionResource, name, subresource string, object runtime.Object) CreateActionImpl {
+ action := CreateActionImpl{}
+ action.Verb = "create"
+ action.Resource = resource
+ action.Subresource = subresource
+ action.Name = name
+ action.Object = object
+
+ return action
+}
+
+func NewCreateSubresourceAction(resource schema.GroupVersionResource, name, subresource, namespace string, object runtime.Object) CreateActionImpl {
+ action := CreateActionImpl{}
+ action.Verb = "create"
+ action.Resource = resource
+ action.Namespace = namespace
+ action.Subresource = subresource
+ action.Name = name
+ action.Object = object
+
+ return action
+}
+
+func NewRootUpdateAction(resource schema.GroupVersionResource, object runtime.Object) UpdateActionImpl {
+ action := UpdateActionImpl{}
+ action.Verb = "update"
+ action.Resource = resource
+ action.Object = object
+
+ return action
+}
+
+func NewUpdateAction(resource schema.GroupVersionResource, namespace string, object runtime.Object) UpdateActionImpl {
+ action := UpdateActionImpl{}
+ action.Verb = "update"
+ action.Resource = resource
+ action.Namespace = namespace
+ action.Object = object
+
+ return action
+}
+
+func NewRootPatchAction(resource schema.GroupVersionResource, name string, pt types.PatchType, patch []byte) PatchActionImpl {
+ action := PatchActionImpl{}
+ action.Verb = "patch"
+ action.Resource = resource
+ action.Name = name
+ action.PatchType = pt
+ action.Patch = patch
+
+ return action
+}
+
+func NewPatchAction(resource schema.GroupVersionResource, namespace string, name string, pt types.PatchType, patch []byte) PatchActionImpl {
+ action := PatchActionImpl{}
+ action.Verb = "patch"
+ action.Resource = resource
+ action.Namespace = namespace
+ action.Name = name
+ action.PatchType = pt
+ action.Patch = patch
+
+ return action
+}
+
+func NewRootPatchSubresourceAction(resource schema.GroupVersionResource, name string, pt types.PatchType, patch []byte, subresources ...string) PatchActionImpl {
+ action := PatchActionImpl{}
+ action.Verb = "patch"
+ action.Resource = resource
+ action.Subresource = path.Join(subresources...)
+ action.Name = name
+ action.PatchType = pt
+ action.Patch = patch
+
+ return action
+}
+
+func NewPatchSubresourceAction(resource schema.GroupVersionResource, namespace, name string, pt types.PatchType, patch []byte, subresources ...string) PatchActionImpl {
+ action := PatchActionImpl{}
+ action.Verb = "patch"
+ action.Resource = resource
+ action.Subresource = path.Join(subresources...)
+ action.Namespace = namespace
+ action.Name = name
+ action.PatchType = pt
+ action.Patch = patch
+
+ return action
+}
+
+func NewRootUpdateSubresourceAction(resource schema.GroupVersionResource, subresource string, object runtime.Object) UpdateActionImpl {
+ action := UpdateActionImpl{}
+ action.Verb = "update"
+ action.Resource = resource
+ action.Subresource = subresource
+ action.Object = object
+
+ return action
+}
+func NewUpdateSubresourceAction(resource schema.GroupVersionResource, subresource string, namespace string, object runtime.Object) UpdateActionImpl {
+ action := UpdateActionImpl{}
+ action.Verb = "update"
+ action.Resource = resource
+ action.Subresource = subresource
+ action.Namespace = namespace
+ action.Object = object
+
+ return action
+}
+
+func NewRootDeleteAction(resource schema.GroupVersionResource, name string) DeleteActionImpl {
+ action := DeleteActionImpl{}
+ action.Verb = "delete"
+ action.Resource = resource
+ action.Name = name
+
+ return action
+}
+
+func NewRootDeleteSubresourceAction(resource schema.GroupVersionResource, subresource string, name string) DeleteActionImpl {
+ action := DeleteActionImpl{}
+ action.Verb = "delete"
+ action.Resource = resource
+ action.Subresource = subresource
+ action.Name = name
+
+ return action
+}
+
+func NewDeleteAction(resource schema.GroupVersionResource, namespace, name string) DeleteActionImpl {
+ action := DeleteActionImpl{}
+ action.Verb = "delete"
+ action.Resource = resource
+ action.Namespace = namespace
+ action.Name = name
+
+ return action
+}
+
+func NewDeleteSubresourceAction(resource schema.GroupVersionResource, subresource, namespace, name string) DeleteActionImpl {
+ action := DeleteActionImpl{}
+ action.Verb = "delete"
+ action.Resource = resource
+ action.Subresource = subresource
+ action.Namespace = namespace
+ action.Name = name
+
+ return action
+}
+
+func NewRootDeleteCollectionAction(resource schema.GroupVersionResource, opts interface{}) DeleteCollectionActionImpl {
+ action := DeleteCollectionActionImpl{}
+ action.Verb = "delete-collection"
+ action.Resource = resource
+ labelSelector, fieldSelector, _ := ExtractFromListOptions(opts)
+ action.ListRestrictions = ListRestrictions{labelSelector, fieldSelector}
+
+ return action
+}
+
+func NewDeleteCollectionAction(resource schema.GroupVersionResource, namespace string, opts interface{}) DeleteCollectionActionImpl {
+ action := DeleteCollectionActionImpl{}
+ action.Verb = "delete-collection"
+ action.Resource = resource
+ action.Namespace = namespace
+ labelSelector, fieldSelector, _ := ExtractFromListOptions(opts)
+ action.ListRestrictions = ListRestrictions{labelSelector, fieldSelector}
+
+ return action
+}
+
+func NewRootWatchAction(resource schema.GroupVersionResource, opts interface{}) WatchActionImpl {
+ action := WatchActionImpl{}
+ action.Verb = "watch"
+ action.Resource = resource
+ labelSelector, fieldSelector, resourceVersion := ExtractFromListOptions(opts)
+ action.WatchRestrictions = WatchRestrictions{labelSelector, fieldSelector, resourceVersion}
+
+ return action
+}
+
+func ExtractFromListOptions(opts interface{}) (labelSelector labels.Selector, fieldSelector fields.Selector, resourceVersion string) {
+ var err error
+ switch t := opts.(type) {
+ case metav1.ListOptions:
+ labelSelector, err = labels.Parse(t.LabelSelector)
+ if err != nil {
+ panic(fmt.Errorf("invalid selector %q: %v", t.LabelSelector, err))
+ }
+ fieldSelector, err = fields.ParseSelector(t.FieldSelector)
+ if err != nil {
+ panic(fmt.Errorf("invalid selector %q: %v", t.FieldSelector, err))
+ }
+ resourceVersion = t.ResourceVersion
+ default:
+ panic(fmt.Errorf("expect a ListOptions %T", opts))
+ }
+ if labelSelector == nil {
+ labelSelector = labels.Everything()
+ }
+ if fieldSelector == nil {
+ fieldSelector = fields.Everything()
+ }
+ return labelSelector, fieldSelector, resourceVersion
+}
+
+func NewWatchAction(resource schema.GroupVersionResource, namespace string, opts interface{}) WatchActionImpl {
+ action := WatchActionImpl{}
+ action.Verb = "watch"
+ action.Resource = resource
+ action.Namespace = namespace
+ labelSelector, fieldSelector, resourceVersion := ExtractFromListOptions(opts)
+ action.WatchRestrictions = WatchRestrictions{labelSelector, fieldSelector, resourceVersion}
+
+ return action
+}
+
+func NewProxyGetAction(resource schema.GroupVersionResource, namespace, scheme, name, port, path string, params map[string]string) ProxyGetActionImpl {
+ action := ProxyGetActionImpl{}
+ action.Verb = "get"
+ action.Resource = resource
+ action.Namespace = namespace
+ action.Scheme = scheme
+ action.Name = name
+ action.Port = port
+ action.Path = path
+ action.Params = params
+ return action
+}
+
+type ListRestrictions struct {
+ Labels labels.Selector
+ Fields fields.Selector
+}
+type WatchRestrictions struct {
+ Labels labels.Selector
+ Fields fields.Selector
+ ResourceVersion string
+}
+
+type Action interface {
+ GetNamespace() string
+ GetVerb() string
+ GetResource() schema.GroupVersionResource
+ GetSubresource() string
+ Matches(verb, resource string) bool
+
+ // DeepCopy is used to copy an action to avoid any risk of accidental mutation. Most people never need to call this
+ // because the invocation logic deep copies before calls to storage and reactors.
+ DeepCopy() Action
+}
+
+type GenericAction interface {
+ Action
+ GetValue() interface{}
+}
+
+type GetAction interface {
+ Action
+ GetName() string
+}
+
+type ListAction interface {
+ Action
+ GetListRestrictions() ListRestrictions
+}
+
+type CreateAction interface {
+ Action
+ GetObject() runtime.Object
+}
+
+type UpdateAction interface {
+ Action
+ GetObject() runtime.Object
+}
+
+type DeleteAction interface {
+ Action
+ GetName() string
+}
+
+type DeleteCollectionAction interface {
+ Action
+ GetListRestrictions() ListRestrictions
+}
+
+type PatchAction interface {
+ Action
+ GetName() string
+ GetPatchType() types.PatchType
+ GetPatch() []byte
+}
+
+type WatchAction interface {
+ Action
+ GetWatchRestrictions() WatchRestrictions
+}
+
+type ProxyGetAction interface {
+ Action
+ GetScheme() string
+ GetName() string
+ GetPort() string
+ GetPath() string
+ GetParams() map[string]string
+}
+
+type ActionImpl struct {
+ Namespace string
+ Verb string
+ Resource schema.GroupVersionResource
+ Subresource string
+}
+
+func (a ActionImpl) GetNamespace() string {
+ return a.Namespace
+}
+func (a ActionImpl) GetVerb() string {
+ return a.Verb
+}
+func (a ActionImpl) GetResource() schema.GroupVersionResource {
+ return a.Resource
+}
+func (a ActionImpl) GetSubresource() string {
+ return a.Subresource
+}
+func (a ActionImpl) Matches(verb, resource string) bool {
+ return strings.ToLower(verb) == strings.ToLower(a.Verb) &&
+ strings.ToLower(resource) == strings.ToLower(a.Resource.Resource)
+}
+func (a ActionImpl) DeepCopy() Action {
+ ret := a
+ return ret
+}
+
+type GenericActionImpl struct {
+ ActionImpl
+ Value interface{}
+}
+
+func (a GenericActionImpl) GetValue() interface{} {
+ return a.Value
+}
+
+func (a GenericActionImpl) DeepCopy() Action {
+ return GenericActionImpl{
+ ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl),
+ // TODO this is wrong, but no worse than before
+ Value: a.Value,
+ }
+}
+
+type GetActionImpl struct {
+ ActionImpl
+ Name string
+}
+
+func (a GetActionImpl) GetName() string {
+ return a.Name
+}
+
+func (a GetActionImpl) DeepCopy() Action {
+ return GetActionImpl{
+ ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl),
+ Name: a.Name,
+ }
+}
+
+type ListActionImpl struct {
+ ActionImpl
+ Kind schema.GroupVersionKind
+ Name string
+ ListRestrictions ListRestrictions
+}
+
+func (a ListActionImpl) GetKind() schema.GroupVersionKind {
+ return a.Kind
+}
+
+func (a ListActionImpl) GetListRestrictions() ListRestrictions {
+ return a.ListRestrictions
+}
+
+func (a ListActionImpl) DeepCopy() Action {
+ return ListActionImpl{
+ ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl),
+ Kind: a.Kind,
+ Name: a.Name,
+ ListRestrictions: ListRestrictions{
+ Labels: a.ListRestrictions.Labels.DeepCopySelector(),
+ Fields: a.ListRestrictions.Fields.DeepCopySelector(),
+ },
+ }
+}
+
+type CreateActionImpl struct {
+ ActionImpl
+ Name string
+ Object runtime.Object
+}
+
+func (a CreateActionImpl) GetObject() runtime.Object {
+ return a.Object
+}
+
+func (a CreateActionImpl) DeepCopy() Action {
+ return CreateActionImpl{
+ ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl),
+ Name: a.Name,
+ Object: a.Object.DeepCopyObject(),
+ }
+}
+
+type UpdateActionImpl struct {
+ ActionImpl
+ Object runtime.Object
+}
+
+func (a UpdateActionImpl) GetObject() runtime.Object {
+ return a.Object
+}
+
+func (a UpdateActionImpl) DeepCopy() Action {
+ return UpdateActionImpl{
+ ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl),
+ Object: a.Object.DeepCopyObject(),
+ }
+}
+
+type PatchActionImpl struct {
+ ActionImpl
+ Name string
+ PatchType types.PatchType
+ Patch []byte
+}
+
+func (a PatchActionImpl) GetName() string {
+ return a.Name
+}
+
+func (a PatchActionImpl) GetPatch() []byte {
+ return a.Patch
+}
+
+func (a PatchActionImpl) GetPatchType() types.PatchType {
+ return a.PatchType
+}
+
+func (a PatchActionImpl) DeepCopy() Action {
+ patch := make([]byte, len(a.Patch))
+ copy(patch, a.Patch)
+ return PatchActionImpl{
+ ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl),
+ Name: a.Name,
+ PatchType: a.PatchType,
+ Patch: patch,
+ }
+}
+
+type DeleteActionImpl struct {
+ ActionImpl
+ Name string
+}
+
+func (a DeleteActionImpl) GetName() string {
+ return a.Name
+}
+
+func (a DeleteActionImpl) DeepCopy() Action {
+ return DeleteActionImpl{
+ ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl),
+ Name: a.Name,
+ }
+}
+
+type DeleteCollectionActionImpl struct {
+ ActionImpl
+ ListRestrictions ListRestrictions
+}
+
+func (a DeleteCollectionActionImpl) GetListRestrictions() ListRestrictions {
+ return a.ListRestrictions
+}
+
+func (a DeleteCollectionActionImpl) DeepCopy() Action {
+ return DeleteCollectionActionImpl{
+ ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl),
+ ListRestrictions: ListRestrictions{
+ Labels: a.ListRestrictions.Labels.DeepCopySelector(),
+ Fields: a.ListRestrictions.Fields.DeepCopySelector(),
+ },
+ }
+}
+
+type WatchActionImpl struct {
+ ActionImpl
+ WatchRestrictions WatchRestrictions
+}
+
+func (a WatchActionImpl) GetWatchRestrictions() WatchRestrictions {
+ return a.WatchRestrictions
+}
+
+func (a WatchActionImpl) DeepCopy() Action {
+ return WatchActionImpl{
+ ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl),
+ WatchRestrictions: WatchRestrictions{
+ Labels: a.WatchRestrictions.Labels.DeepCopySelector(),
+ Fields: a.WatchRestrictions.Fields.DeepCopySelector(),
+ ResourceVersion: a.WatchRestrictions.ResourceVersion,
+ },
+ }
+}
+
+type ProxyGetActionImpl struct {
+ ActionImpl
+ Scheme string
+ Name string
+ Port string
+ Path string
+ Params map[string]string
+}
+
+func (a ProxyGetActionImpl) GetScheme() string {
+ return a.Scheme
+}
+
+func (a ProxyGetActionImpl) GetName() string {
+ return a.Name
+}
+
+func (a ProxyGetActionImpl) GetPort() string {
+ return a.Port
+}
+
+func (a ProxyGetActionImpl) GetPath() string {
+ return a.Path
+}
+
+func (a ProxyGetActionImpl) GetParams() map[string]string {
+ return a.Params
+}
+
+func (a ProxyGetActionImpl) DeepCopy() Action {
+ params := map[string]string{}
+ for k, v := range a.Params {
+ params[k] = v
+ }
+ return ProxyGetActionImpl{
+ ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl),
+ Scheme: a.Scheme,
+ Name: a.Name,
+ Port: a.Port,
+ Path: a.Path,
+ Params: params,
+ }
+}
diff --git a/vendor/k8s.io/client-go/testing/fake.go b/vendor/k8s.io/client-go/testing/fake.go
new file mode 100644
index 000000000..8b9ee149c
--- /dev/null
+++ b/vendor/k8s.io/client-go/testing/fake.go
@@ -0,0 +1,216 @@
+/*
+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 testing
+
+import (
+ "fmt"
+ "sync"
+
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/watch"
+ restclient "k8s.io/client-go/rest"
+)
+
+// Fake implements client.Interface. Meant to be embedded into a struct to get
+// a default implementation. This makes faking out just the method you want to
+// test easier.
+type Fake struct {
+ sync.RWMutex
+ actions []Action // these may be castable to other types, but "Action" is the minimum
+
+ // ReactionChain is the list of reactors that will be attempted for every
+ // request in the order they are tried.
+ ReactionChain []Reactor
+ // WatchReactionChain is the list of watch reactors that will be attempted
+ // for every request in the order they are tried.
+ WatchReactionChain []WatchReactor
+ // ProxyReactionChain is the list of proxy reactors that will be attempted
+ // for every request in the order they are tried.
+ ProxyReactionChain []ProxyReactor
+
+ Resources []*metav1.APIResourceList
+}
+
+// Reactor is an interface to allow the composition of reaction functions.
+type Reactor interface {
+ // Handles indicates whether or not this Reactor deals with a given
+ // action.
+ Handles(action Action) bool
+ // React handles the action and returns results. It may choose to
+ // delegate by indicated handled=false.
+ React(action Action) (handled bool, ret runtime.Object, err error)
+}
+
+// WatchReactor is an interface to allow the composition of watch functions.
+type WatchReactor interface {
+ // Handles indicates whether or not this Reactor deals with a given
+ // action.
+ Handles(action Action) bool
+ // React handles a watch action and returns results. It may choose to
+ // delegate by indicating handled=false.
+ React(action Action) (handled bool, ret watch.Interface, err error)
+}
+
+// ProxyReactor is an interface to allow the composition of proxy get
+// functions.
+type ProxyReactor interface {
+ // Handles indicates whether or not this Reactor deals with a given
+ // action.
+ Handles(action Action) bool
+ // React handles a watch action and returns results. It may choose to
+ // delegate by indicating handled=false.
+ React(action Action) (handled bool, ret restclient.ResponseWrapper, err error)
+}
+
+// ReactionFunc is a function that returns an object or error for a given
+// Action. If "handled" is false, then the test client will ignore the
+// results and continue to the next ReactionFunc. A ReactionFunc can describe
+// reactions on subresources by testing the result of the action's
+// GetSubresource() method.
+type ReactionFunc func(action Action) (handled bool, ret runtime.Object, err error)
+
+// WatchReactionFunc is a function that returns a watch interface. If
+// "handled" is false, then the test client will ignore the results and
+// continue to the next ReactionFunc.
+type WatchReactionFunc func(action Action) (handled bool, ret watch.Interface, err error)
+
+// ProxyReactionFunc is a function that returns a ResponseWrapper interface
+// for a given Action. If "handled" is false, then the test client will
+// ignore the results and continue to the next ProxyReactionFunc.
+type ProxyReactionFunc func(action Action) (handled bool, ret restclient.ResponseWrapper, err error)
+
+// AddReactor appends a reactor to the end of the chain.
+func (c *Fake) AddReactor(verb, resource string, reaction ReactionFunc) {
+ c.ReactionChain = append(c.ReactionChain, &SimpleReactor{verb, resource, reaction})
+}
+
+// PrependReactor adds a reactor to the beginning of the chain.
+func (c *Fake) PrependReactor(verb, resource string, reaction ReactionFunc) {
+ c.ReactionChain = append([]Reactor{&SimpleReactor{verb, resource, reaction}}, c.ReactionChain...)
+}
+
+// AddWatchReactor appends a reactor to the end of the chain.
+func (c *Fake) AddWatchReactor(resource string, reaction WatchReactionFunc) {
+ c.WatchReactionChain = append(c.WatchReactionChain, &SimpleWatchReactor{resource, reaction})
+}
+
+// PrependWatchReactor adds a reactor to the beginning of the chain.
+func (c *Fake) PrependWatchReactor(resource string, reaction WatchReactionFunc) {
+ c.WatchReactionChain = append([]WatchReactor{&SimpleWatchReactor{resource, reaction}}, c.WatchReactionChain...)
+}
+
+// AddProxyReactor appends a reactor to the end of the chain.
+func (c *Fake) AddProxyReactor(resource string, reaction ProxyReactionFunc) {
+ c.ProxyReactionChain = append(c.ProxyReactionChain, &SimpleProxyReactor{resource, reaction})
+}
+
+// PrependProxyReactor adds a reactor to the beginning of the chain.
+func (c *Fake) PrependProxyReactor(resource string, reaction ProxyReactionFunc) {
+ c.ProxyReactionChain = append([]ProxyReactor{&SimpleProxyReactor{resource, reaction}}, c.ProxyReactionChain...)
+}
+
+// Invokes records the provided Action and then invokes the ReactionFunc that
+// handles the action if one exists. defaultReturnObj is expected to be of the
+// same type a normal call would return.
+func (c *Fake) Invokes(action Action, defaultReturnObj runtime.Object) (runtime.Object, error) {
+ c.Lock()
+ defer c.Unlock()
+
+ actionCopy := action.DeepCopy()
+ c.actions = append(c.actions, action.DeepCopy())
+ for _, reactor := range c.ReactionChain {
+ if !reactor.Handles(actionCopy) {
+ continue
+ }
+
+ handled, ret, err := reactor.React(actionCopy)
+ if !handled {
+ continue
+ }
+
+ return ret, err
+ }
+
+ return defaultReturnObj, nil
+}
+
+// InvokesWatch records the provided Action and then invokes the ReactionFunc
+// that handles the action if one exists.
+func (c *Fake) InvokesWatch(action Action) (watch.Interface, error) {
+ c.Lock()
+ defer c.Unlock()
+
+ actionCopy := action.DeepCopy()
+ c.actions = append(c.actions, action.DeepCopy())
+ for _, reactor := range c.WatchReactionChain {
+ if !reactor.Handles(actionCopy) {
+ continue
+ }
+
+ handled, ret, err := reactor.React(actionCopy)
+ if !handled {
+ continue
+ }
+
+ return ret, err
+ }
+
+ return nil, fmt.Errorf("unhandled watch: %#v", action)
+}
+
+// InvokesProxy records the provided Action and then invokes the ReactionFunc
+// that handles the action if one exists.
+func (c *Fake) InvokesProxy(action Action) restclient.ResponseWrapper {
+ c.Lock()
+ defer c.Unlock()
+
+ actionCopy := action.DeepCopy()
+ c.actions = append(c.actions, action.DeepCopy())
+ for _, reactor := range c.ProxyReactionChain {
+ if !reactor.Handles(actionCopy) {
+ continue
+ }
+
+ handled, ret, err := reactor.React(actionCopy)
+ if !handled || err != nil {
+ continue
+ }
+
+ return ret
+ }
+
+ return nil
+}
+
+// ClearActions clears the history of actions called on the fake client.
+func (c *Fake) ClearActions() {
+ c.Lock()
+ defer c.Unlock()
+
+ c.actions = make([]Action, 0)
+}
+
+// Actions returns a chronologically ordered slice fake actions called on the
+// fake client.
+func (c *Fake) Actions() []Action {
+ c.RLock()
+ defer c.RUnlock()
+ fa := make([]Action, len(c.actions))
+ copy(fa, c.actions)
+ return fa
+}
diff --git a/vendor/k8s.io/client-go/testing/fixture.go b/vendor/k8s.io/client-go/testing/fixture.go
new file mode 100644
index 000000000..993fcf6a1
--- /dev/null
+++ b/vendor/k8s.io/client-go/testing/fixture.go
@@ -0,0 +1,557 @@
+/*
+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 testing
+
+import (
+ "fmt"
+ "sync"
+
+ jsonpatch "github.com/evanphx/json-patch"
+ "k8s.io/apimachinery/pkg/api/errors"
+ "k8s.io/apimachinery/pkg/api/meta"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/apimachinery/pkg/types"
+ "k8s.io/apimachinery/pkg/util/json"
+ "k8s.io/apimachinery/pkg/util/strategicpatch"
+ "k8s.io/apimachinery/pkg/watch"
+ restclient "k8s.io/client-go/rest"
+)
+
+// ObjectTracker keeps track of objects. It is intended to be used to
+// fake calls to a server by returning objects based on their kind,
+// namespace and name.
+type ObjectTracker interface {
+ // Add adds an object to the tracker. If object being added
+ // is a list, its items are added separately.
+ Add(obj runtime.Object) error
+
+ // Get retrieves the object by its kind, namespace and name.
+ Get(gvr schema.GroupVersionResource, ns, name string) (runtime.Object, error)
+
+ // Create adds an object to the tracker in the specified namespace.
+ Create(gvr schema.GroupVersionResource, obj runtime.Object, ns string) error
+
+ // Update updates an existing object in the tracker in the specified namespace.
+ Update(gvr schema.GroupVersionResource, obj runtime.Object, ns string) error
+
+ // List retrieves all objects of a given kind in the given
+ // namespace. Only non-List kinds are accepted.
+ List(gvr schema.GroupVersionResource, gvk schema.GroupVersionKind, ns string) (runtime.Object, error)
+
+ // Delete deletes an existing object from the tracker. If object
+ // didn't exist in the tracker prior to deletion, Delete returns
+ // no error.
+ Delete(gvr schema.GroupVersionResource, ns, name string) error
+
+ // Watch watches objects from the tracker. Watch returns a channel
+ // which will push added / modified / deleted object.
+ Watch(gvr schema.GroupVersionResource, ns string) (watch.Interface, error)
+}
+
+// ObjectScheme abstracts the implementation of common operations on objects.
+type ObjectScheme interface {
+ runtime.ObjectCreater
+ runtime.ObjectTyper
+}
+
+// ObjectReaction returns a ReactionFunc that applies core.Action to
+// the given tracker.
+func ObjectReaction(tracker ObjectTracker) ReactionFunc {
+ return func(action Action) (bool, runtime.Object, error) {
+ ns := action.GetNamespace()
+ gvr := action.GetResource()
+ // Here and below we need to switch on implementation types,
+ // not on interfaces, as some interfaces are identical
+ // (e.g. UpdateAction and CreateAction), so if we use them,
+ // updates and creates end up matching the same case branch.
+ switch action := action.(type) {
+
+ case ListActionImpl:
+ obj, err := tracker.List(gvr, action.GetKind(), ns)
+ return true, obj, err
+
+ case GetActionImpl:
+ obj, err := tracker.Get(gvr, ns, action.GetName())
+ return true, obj, err
+
+ case CreateActionImpl:
+ objMeta, err := meta.Accessor(action.GetObject())
+ if err != nil {
+ return true, nil, err
+ }
+ if action.GetSubresource() == "" {
+ err = tracker.Create(gvr, action.GetObject(), ns)
+ } else {
+ // TODO: Currently we're handling subresource creation as an update
+ // on the enclosing resource. This works for some subresources but
+ // might not be generic enough.
+ err = tracker.Update(gvr, action.GetObject(), ns)
+ }
+ if err != nil {
+ return true, nil, err
+ }
+ obj, err := tracker.Get(gvr, ns, objMeta.GetName())
+ return true, obj, err
+
+ case UpdateActionImpl:
+ objMeta, err := meta.Accessor(action.GetObject())
+ if err != nil {
+ return true, nil, err
+ }
+ err = tracker.Update(gvr, action.GetObject(), ns)
+ if err != nil {
+ return true, nil, err
+ }
+ obj, err := tracker.Get(gvr, ns, objMeta.GetName())
+ return true, obj, err
+
+ case DeleteActionImpl:
+ err := tracker.Delete(gvr, ns, action.GetName())
+ if err != nil {
+ return true, nil, err
+ }
+ return true, nil, nil
+
+ case PatchActionImpl:
+ obj, err := tracker.Get(gvr, ns, action.GetName())
+ if err != nil {
+ return true, nil, err
+ }
+
+ old, err := json.Marshal(obj)
+ if err != nil {
+ return true, nil, err
+ }
+
+ switch action.GetPatchType() {
+ case types.JSONPatchType:
+ patch, err := jsonpatch.DecodePatch(action.GetPatch())
+ if err != nil {
+ return true, nil, err
+ }
+ modified, err := patch.Apply(old)
+ if err != nil {
+ return true, nil, err
+ }
+ if err = json.Unmarshal(modified, obj); err != nil {
+ return true, nil, err
+ }
+ case types.MergePatchType:
+ modified, err := jsonpatch.MergePatch(old, action.GetPatch())
+ if err != nil {
+ return true, nil, err
+ }
+
+ if err := json.Unmarshal(modified, obj); err != nil {
+ return true, nil, err
+ }
+ case types.StrategicMergePatchType:
+ mergedByte, err := strategicpatch.StrategicMergePatch(old, action.GetPatch(), obj)
+ if err != nil {
+ return true, nil, err
+ }
+ if err = json.Unmarshal(mergedByte, obj); err != nil {
+ return true, nil, err
+ }
+ default:
+ return true, nil, fmt.Errorf("PatchType is not supported")
+ }
+
+ if err = tracker.Update(gvr, obj, ns); err != nil {
+ return true, nil, err
+ }
+
+ return true, obj, nil
+
+ default:
+ return false, nil, fmt.Errorf("no reaction implemented for %s", action)
+ }
+ }
+}
+
+type tracker struct {
+ scheme ObjectScheme
+ decoder runtime.Decoder
+ lock sync.RWMutex
+ objects map[schema.GroupVersionResource][]runtime.Object
+ // The value type of watchers is a map of which the key is either a namespace or
+ // all/non namespace aka "" and its value is list of fake watchers.
+ // Manipulations on resources will broadcast the notification events into the
+ // watchers' channel. Note that too many unhandled events (currently 100,
+ // see apimachinery/pkg/watch.DefaultChanSize) will cause a panic.
+ watchers map[schema.GroupVersionResource]map[string][]*watch.RaceFreeFakeWatcher
+}
+
+var _ ObjectTracker = &tracker{}
+
+// NewObjectTracker returns an ObjectTracker that can be used to keep track
+// of objects for the fake clientset. Mostly useful for unit tests.
+func NewObjectTracker(scheme ObjectScheme, decoder runtime.Decoder) ObjectTracker {
+ return &tracker{
+ scheme: scheme,
+ decoder: decoder,
+ objects: make(map[schema.GroupVersionResource][]runtime.Object),
+ watchers: make(map[schema.GroupVersionResource]map[string][]*watch.RaceFreeFakeWatcher),
+ }
+}
+
+func (t *tracker) List(gvr schema.GroupVersionResource, gvk schema.GroupVersionKind, ns string) (runtime.Object, error) {
+ // Heuristic for list kind: original kind + List suffix. Might
+ // not always be true but this tracker has a pretty limited
+ // understanding of the actual API model.
+ listGVK := gvk
+ listGVK.Kind = listGVK.Kind + "List"
+ // GVK does have the concept of "internal version". The scheme recognizes
+ // the runtime.APIVersionInternal, but not the empty string.
+ if listGVK.Version == "" {
+ listGVK.Version = runtime.APIVersionInternal
+ }
+
+ list, err := t.scheme.New(listGVK)
+ if err != nil {
+ return nil, err
+ }
+
+ if !meta.IsListType(list) {
+ return nil, fmt.Errorf("%q is not a list type", listGVK.Kind)
+ }
+
+ t.lock.RLock()
+ defer t.lock.RUnlock()
+
+ objs, ok := t.objects[gvr]
+ if !ok {
+ return list, nil
+ }
+
+ matchingObjs, err := filterByNamespaceAndName(objs, ns, "")
+ if err != nil {
+ return nil, err
+ }
+ if err := meta.SetList(list, matchingObjs); err != nil {
+ return nil, err
+ }
+ return list.DeepCopyObject(), nil
+}
+
+func (t *tracker) Watch(gvr schema.GroupVersionResource, ns string) (watch.Interface, error) {
+ t.lock.Lock()
+ defer t.lock.Unlock()
+
+ fakewatcher := watch.NewRaceFreeFake()
+
+ if _, exists := t.watchers[gvr]; !exists {
+ t.watchers[gvr] = make(map[string][]*watch.RaceFreeFakeWatcher)
+ }
+ t.watchers[gvr][ns] = append(t.watchers[gvr][ns], fakewatcher)
+ return fakewatcher, nil
+}
+
+func (t *tracker) Get(gvr schema.GroupVersionResource, ns, name string) (runtime.Object, error) {
+ errNotFound := errors.NewNotFound(gvr.GroupResource(), name)
+
+ t.lock.RLock()
+ defer t.lock.RUnlock()
+
+ objs, ok := t.objects[gvr]
+ if !ok {
+ return nil, errNotFound
+ }
+
+ matchingObjs, err := filterByNamespaceAndName(objs, ns, name)
+ if err != nil {
+ return nil, err
+ }
+ if len(matchingObjs) == 0 {
+ return nil, errNotFound
+ }
+ if len(matchingObjs) > 1 {
+ return nil, fmt.Errorf("more than one object matched gvr %s, ns: %q name: %q", gvr, ns, name)
+ }
+
+ // Only one object should match in the tracker if it works
+ // correctly, as Add/Update methods enforce kind/namespace/name
+ // uniqueness.
+ obj := matchingObjs[0].DeepCopyObject()
+ if status, ok := obj.(*metav1.Status); ok {
+ if status.Status != metav1.StatusSuccess {
+ return nil, &errors.StatusError{ErrStatus: *status}
+ }
+ }
+
+ return obj, nil
+}
+
+func (t *tracker) Add(obj runtime.Object) error {
+ if meta.IsListType(obj) {
+ return t.addList(obj, false)
+ }
+ objMeta, err := meta.Accessor(obj)
+ if err != nil {
+ return err
+ }
+ gvks, _, err := t.scheme.ObjectKinds(obj)
+ if err != nil {
+ return err
+ }
+ if len(gvks) == 0 {
+ return fmt.Errorf("no registered kinds for %v", obj)
+ }
+ for _, gvk := range gvks {
+ // NOTE: UnsafeGuessKindToResource is a heuristic and default match. The
+ // actual registration in apiserver can specify arbitrary route for a
+ // gvk. If a test uses such objects, it cannot preset the tracker with
+ // objects via Add(). Instead, it should trigger the Create() function
+ // of the tracker, where an arbitrary gvr can be specified.
+ gvr, _ := meta.UnsafeGuessKindToResource(gvk)
+ // Resource doesn't have the concept of "__internal" version, just set it to "".
+ if gvr.Version == runtime.APIVersionInternal {
+ gvr.Version = ""
+ }
+
+ err := t.add(gvr, obj, objMeta.GetNamespace(), false)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (t *tracker) Create(gvr schema.GroupVersionResource, obj runtime.Object, ns string) error {
+ return t.add(gvr, obj, ns, false)
+}
+
+func (t *tracker) Update(gvr schema.GroupVersionResource, obj runtime.Object, ns string) error {
+ return t.add(gvr, obj, ns, true)
+}
+
+func (t *tracker) getWatches(gvr schema.GroupVersionResource, ns string) []*watch.RaceFreeFakeWatcher {
+ watches := []*watch.RaceFreeFakeWatcher{}
+ if t.watchers[gvr] != nil {
+ if w := t.watchers[gvr][ns]; w != nil {
+ watches = append(watches, w...)
+ }
+ if ns != metav1.NamespaceAll {
+ if w := t.watchers[gvr][metav1.NamespaceAll]; w != nil {
+ watches = append(watches, w...)
+ }
+ }
+ }
+ return watches
+}
+
+func (t *tracker) add(gvr schema.GroupVersionResource, obj runtime.Object, ns string, replaceExisting bool) error {
+ t.lock.Lock()
+ defer t.lock.Unlock()
+
+ gr := gvr.GroupResource()
+
+ // To avoid the object from being accidentally modified by caller
+ // after it's been added to the tracker, we always store the deep
+ // copy.
+ obj = obj.DeepCopyObject()
+
+ newMeta, err := meta.Accessor(obj)
+ if err != nil {
+ return err
+ }
+
+ // Propagate namespace to the new object if hasn't already been set.
+ if len(newMeta.GetNamespace()) == 0 {
+ newMeta.SetNamespace(ns)
+ }
+
+ if ns != newMeta.GetNamespace() {
+ msg := fmt.Sprintf("request namespace does not match object namespace, request: %q object: %q", ns, newMeta.GetNamespace())
+ return errors.NewBadRequest(msg)
+ }
+
+ for i, existingObj := range t.objects[gvr] {
+ oldMeta, err := meta.Accessor(existingObj)
+ if err != nil {
+ return err
+ }
+ if oldMeta.GetNamespace() == newMeta.GetNamespace() && oldMeta.GetName() == newMeta.GetName() {
+ if replaceExisting {
+ for _, w := range t.getWatches(gvr, ns) {
+ w.Modify(obj)
+ }
+ t.objects[gvr][i] = obj
+ return nil
+ }
+ return errors.NewAlreadyExists(gr, newMeta.GetName())
+ }
+ }
+
+ if replaceExisting {
+ // Tried to update but no matching object was found.
+ return errors.NewNotFound(gr, newMeta.GetName())
+ }
+
+ t.objects[gvr] = append(t.objects[gvr], obj)
+
+ for _, w := range t.getWatches(gvr, ns) {
+ w.Add(obj)
+ }
+
+ return nil
+}
+
+func (t *tracker) addList(obj runtime.Object, replaceExisting bool) error {
+ list, err := meta.ExtractList(obj)
+ if err != nil {
+ return err
+ }
+ errs := runtime.DecodeList(list, t.decoder)
+ if len(errs) > 0 {
+ return errs[0]
+ }
+ for _, obj := range list {
+ if err := t.Add(obj); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (t *tracker) Delete(gvr schema.GroupVersionResource, ns, name string) error {
+ t.lock.Lock()
+ defer t.lock.Unlock()
+
+ found := false
+
+ for i, existingObj := range t.objects[gvr] {
+ objMeta, err := meta.Accessor(existingObj)
+ if err != nil {
+ return err
+ }
+ if objMeta.GetNamespace() == ns && objMeta.GetName() == name {
+ obj := t.objects[gvr][i]
+ t.objects[gvr] = append(t.objects[gvr][:i], t.objects[gvr][i+1:]...)
+ for _, w := range t.getWatches(gvr, ns) {
+ w.Delete(obj)
+ }
+ found = true
+ break
+ }
+ }
+
+ if found {
+ return nil
+ }
+
+ return errors.NewNotFound(gvr.GroupResource(), name)
+}
+
+// filterByNamespaceAndName returns all objects in the collection that
+// match provided namespace and name. Empty namespace matches
+// non-namespaced objects.
+func filterByNamespaceAndName(objs []runtime.Object, ns, name string) ([]runtime.Object, error) {
+ var res []runtime.Object
+
+ for _, obj := range objs {
+ acc, err := meta.Accessor(obj)
+ if err != nil {
+ return nil, err
+ }
+ if ns != "" && acc.GetNamespace() != ns {
+ continue
+ }
+ if name != "" && acc.GetName() != name {
+ continue
+ }
+ res = append(res, obj)
+ }
+
+ return res, nil
+}
+
+func DefaultWatchReactor(watchInterface watch.Interface, err error) WatchReactionFunc {
+ return func(action Action) (bool, watch.Interface, error) {
+ return true, watchInterface, err
+ }
+}
+
+// SimpleReactor is a Reactor. Each reaction function is attached to a given verb,resource tuple. "*" in either field matches everything for that value.
+// For instance, *,pods matches all verbs on pods. This allows for easier composition of reaction functions
+type SimpleReactor struct {
+ Verb string
+ Resource string
+
+ Reaction ReactionFunc
+}
+
+func (r *SimpleReactor) Handles(action Action) bool {
+ verbCovers := r.Verb == "*" || r.Verb == action.GetVerb()
+ if !verbCovers {
+ return false
+ }
+ resourceCovers := r.Resource == "*" || r.Resource == action.GetResource().Resource
+ if !resourceCovers {
+ return false
+ }
+
+ return true
+}
+
+func (r *SimpleReactor) React(action Action) (bool, runtime.Object, error) {
+ return r.Reaction(action)
+}
+
+// SimpleWatchReactor is a WatchReactor. Each reaction function is attached to a given resource. "*" matches everything for that value.
+// For instance, *,pods matches all verbs on pods. This allows for easier composition of reaction functions
+type SimpleWatchReactor struct {
+ Resource string
+
+ Reaction WatchReactionFunc
+}
+
+func (r *SimpleWatchReactor) Handles(action Action) bool {
+ resourceCovers := r.Resource == "*" || r.Resource == action.GetResource().Resource
+ if !resourceCovers {
+ return false
+ }
+
+ return true
+}
+
+func (r *SimpleWatchReactor) React(action Action) (bool, watch.Interface, error) {
+ return r.Reaction(action)
+}
+
+// SimpleProxyReactor is a ProxyReactor. Each reaction function is attached to a given resource. "*" matches everything for that value.
+// For instance, *,pods matches all verbs on pods. This allows for easier composition of reaction functions.
+type SimpleProxyReactor struct {
+ Resource string
+
+ Reaction ProxyReactionFunc
+}
+
+func (r *SimpleProxyReactor) Handles(action Action) bool {
+ resourceCovers := r.Resource == "*" || r.Resource == action.GetResource().Resource
+ if !resourceCovers {
+ return false
+ }
+
+ return true
+}
+
+func (r *SimpleProxyReactor) React(action Action) (bool, restclient.ResponseWrapper, error) {
+ return r.Reaction(action)
+}
diff --git a/vendor/k8s.io/kube-openapi/LICENSE b/vendor/k8s.io/kube-openapi/LICENSE
new file mode 100644
index 000000000..d64569567
--- /dev/null
+++ b/vendor/k8s.io/kube-openapi/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/vendor/k8s.io/kube-openapi/pkg/util/proto/OWNERS b/vendor/k8s.io/kube-openapi/pkg/util/proto/OWNERS
new file mode 100644
index 000000000..9621a6a3a
--- /dev/null
+++ b/vendor/k8s.io/kube-openapi/pkg/util/proto/OWNERS
@@ -0,0 +1,2 @@
+approvers:
+- apelisse
diff --git a/vendor/k8s.io/kube-openapi/pkg/util/proto/doc.go b/vendor/k8s.io/kube-openapi/pkg/util/proto/doc.go
new file mode 100644
index 000000000..11ed8a6b7
--- /dev/null
+++ b/vendor/k8s.io/kube-openapi/pkg/util/proto/doc.go
@@ -0,0 +1,19 @@
+/*
+Copyright 2017 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 proto is a collection of libraries for parsing and indexing the type definitions.
+// The openapi spec contains the object model definitions and extensions metadata.
+package proto
diff --git a/vendor/k8s.io/kube-openapi/pkg/util/proto/document.go b/vendor/k8s.io/kube-openapi/pkg/util/proto/document.go
new file mode 100644
index 000000000..5eb957aff
--- /dev/null
+++ b/vendor/k8s.io/kube-openapi/pkg/util/proto/document.go
@@ -0,0 +1,318 @@
+/*
+Copyright 2017 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 proto
+
+import (
+ "fmt"
+ "sort"
+ "strings"
+
+ "github.com/googleapis/gnostic/OpenAPIv2"
+ "gopkg.in/yaml.v2"
+)
+
+func newSchemaError(path *Path, format string, a ...interface{}) error {
+ err := fmt.Sprintf(format, a...)
+ if path.Len() == 0 {
+ return fmt.Errorf("SchemaError: %v", err)
+ }
+ return fmt.Errorf("SchemaError(%v): %v", path, err)
+}
+
+// VendorExtensionToMap converts openapi VendorExtension to a map.
+func VendorExtensionToMap(e []*openapi_v2.NamedAny) map[string]interface{} {
+ values := map[string]interface{}{}
+
+ for _, na := range e {
+ if na.GetName() == "" || na.GetValue() == nil {
+ continue
+ }
+ if na.GetValue().GetYaml() == "" {
+ continue
+ }
+ var value interface{}
+ err := yaml.Unmarshal([]byte(na.GetValue().GetYaml()), &value)
+ if err != nil {
+ continue
+ }
+
+ values[na.GetName()] = value
+ }
+
+ return values
+}
+
+// Definitions is an implementation of `Models`. It looks for
+// models in an openapi Schema.
+type Definitions struct {
+ models map[string]Schema
+}
+
+var _ Models = &Definitions{}
+
+// NewOpenAPIData creates a new `Models` out of the openapi document.
+func NewOpenAPIData(doc *openapi_v2.Document) (Models, error) {
+ definitions := Definitions{
+ models: map[string]Schema{},
+ }
+
+ // Save the list of all models first. This will allow us to
+ // validate that we don't have any dangling reference.
+ for _, namedSchema := range doc.GetDefinitions().GetAdditionalProperties() {
+ definitions.models[namedSchema.GetName()] = nil
+ }
+
+ // Now, parse each model. We can validate that references exists.
+ for _, namedSchema := range doc.GetDefinitions().GetAdditionalProperties() {
+ path := NewPath(namedSchema.GetName())
+ schema, err := definitions.ParseSchema(namedSchema.GetValue(), &path)
+ if err != nil {
+ return nil, err
+ }
+ definitions.models[namedSchema.GetName()] = schema
+ }
+
+ return &definitions, nil
+}
+
+// We believe the schema is a reference, verify that and returns a new
+// Schema
+func (d *Definitions) parseReference(s *openapi_v2.Schema, path *Path) (Schema, error) {
+ // TODO(wrong): a schema with a $ref can have properties. We can ignore them (would be incomplete), but we cannot return an error.
+ if len(s.GetProperties().GetAdditionalProperties()) > 0 {
+ return nil, newSchemaError(path, "unallowed embedded type definition")
+ }
+ // TODO(wrong): a schema with a $ref can have a type. We can ignore it (would be incomplete), but we cannot return an error.
+ if len(s.GetType().GetValue()) > 0 {
+ return nil, newSchemaError(path, "definition reference can't have a type")
+ }
+
+ // TODO(wrong): $refs outside of the definitions are completely valid. We can ignore them (would be incomplete), but we cannot return an error.
+ if !strings.HasPrefix(s.GetXRef(), "#/definitions/") {
+ return nil, newSchemaError(path, "unallowed reference to non-definition %q", s.GetXRef())
+ }
+ reference := strings.TrimPrefix(s.GetXRef(), "#/definitions/")
+ if _, ok := d.models[reference]; !ok {
+ return nil, newSchemaError(path, "unknown model in reference: %q", reference)
+ }
+ return &Ref{
+ BaseSchema: d.parseBaseSchema(s, path),
+ reference: reference,
+ definitions: d,
+ }, nil
+}
+
+func (d *Definitions) parseBaseSchema(s *openapi_v2.Schema, path *Path) BaseSchema {
+ return BaseSchema{
+ Description: s.GetDescription(),
+ Extensions: VendorExtensionToMap(s.GetVendorExtension()),
+ Path: *path,
+ }
+}
+
+// We believe the schema is a map, verify and return a new schema
+func (d *Definitions) parseMap(s *openapi_v2.Schema, path *Path) (Schema, error) {
+ if len(s.GetType().GetValue()) != 0 && s.GetType().GetValue()[0] != object {
+ return nil, newSchemaError(path, "invalid object type")
+ }
+ var sub Schema
+ // TODO(incomplete): this misses the boolean case as AdditionalProperties is a bool+schema sum type.
+ if s.GetAdditionalProperties().GetSchema() == nil {
+ sub = &Arbitrary{
+ BaseSchema: d.parseBaseSchema(s, path),
+ }
+ } else {
+ var err error
+ sub, err = d.ParseSchema(s.GetAdditionalProperties().GetSchema(), path)
+ if err != nil {
+ return nil, err
+ }
+ }
+ return &Map{
+ BaseSchema: d.parseBaseSchema(s, path),
+ SubType: sub,
+ }, nil
+}
+
+func (d *Definitions) parsePrimitive(s *openapi_v2.Schema, path *Path) (Schema, error) {
+ var t string
+ if len(s.GetType().GetValue()) > 1 {
+ return nil, newSchemaError(path, "primitive can't have more than 1 type")
+ }
+ if len(s.GetType().GetValue()) == 1 {
+ t = s.GetType().GetValue()[0]
+ }
+ switch t {
+ case String: // do nothing
+ case Number: // do nothing
+ case Integer: // do nothing
+ case Boolean: // do nothing
+ // TODO(wrong): this misses "null". Would skip the null case (would be incomplete), but we cannot return an error.
+ default:
+ return nil, newSchemaError(path, "Unknown primitive type: %q", t)
+ }
+ return &Primitive{
+ BaseSchema: d.parseBaseSchema(s, path),
+ Type: t,
+ Format: s.GetFormat(),
+ }, nil
+}
+
+func (d *Definitions) parseArray(s *openapi_v2.Schema, path *Path) (Schema, error) {
+ if len(s.GetType().GetValue()) != 1 {
+ return nil, newSchemaError(path, "array should have exactly one type")
+ }
+ if s.GetType().GetValue()[0] != array {
+ return nil, newSchemaError(path, `array should have type "array"`)
+ }
+ if len(s.GetItems().GetSchema()) != 1 {
+ // TODO(wrong): Items can have multiple elements. We can ignore Items then (would be incomplete), but we cannot return an error.
+ // TODO(wrong): "type: array" witohut any items at all is completely valid.
+ return nil, newSchemaError(path, "array should have exactly one sub-item")
+ }
+ sub, err := d.ParseSchema(s.GetItems().GetSchema()[0], path)
+ if err != nil {
+ return nil, err
+ }
+ return &Array{
+ BaseSchema: d.parseBaseSchema(s, path),
+ SubType: sub,
+ }, nil
+}
+
+func (d *Definitions) parseKind(s *openapi_v2.Schema, path *Path) (Schema, error) {
+ if len(s.GetType().GetValue()) != 0 && s.GetType().GetValue()[0] != object {
+ return nil, newSchemaError(path, "invalid object type")
+ }
+ if s.GetProperties() == nil {
+ return nil, newSchemaError(path, "object doesn't have properties")
+ }
+
+ fields := map[string]Schema{}
+ fieldOrder := []string{}
+
+ for _, namedSchema := range s.GetProperties().GetAdditionalProperties() {
+ var err error
+ name := namedSchema.GetName()
+ path := path.FieldPath(name)
+ fields[name], err = d.ParseSchema(namedSchema.GetValue(), &path)
+ if err != nil {
+ return nil, err
+ }
+ fieldOrder = append(fieldOrder, name)
+ }
+
+ return &Kind{
+ BaseSchema: d.parseBaseSchema(s, path),
+ RequiredFields: s.GetRequired(),
+ Fields: fields,
+ FieldOrder: fieldOrder,
+ }, nil
+}
+
+func (d *Definitions) parseArbitrary(s *openapi_v2.Schema, path *Path) (Schema, error) {
+ return &Arbitrary{
+ BaseSchema: d.parseBaseSchema(s, path),
+ }, nil
+}
+
+// ParseSchema creates a walkable Schema from an openapi schema. While
+// this function is public, it doesn't leak through the interface.
+func (d *Definitions) ParseSchema(s *openapi_v2.Schema, path *Path) (Schema, error) {
+ if s.GetXRef() != "" {
+ // TODO(incomplete): ignoring the rest of s is wrong. As long as there are no conflict, everything from s must be considered
+ // Reference: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#path-item-object
+ return d.parseReference(s, path)
+ }
+ objectTypes := s.GetType().GetValue()
+ switch len(objectTypes) {
+ case 0:
+ // in the OpenAPI schema served by older k8s versions, object definitions created from structs did not include
+ // the type:object property (they only included the "properties" property), so we need to handle this case
+ // TODO: validate that we ever published empty, non-nil properties. JSON roundtripping nils them.
+ if s.GetProperties() != nil {
+ // TODO(wrong): when verifying a non-object later against this, it will be rejected as invalid type.
+ // TODO(CRD validation schema publishing): we have to filter properties (empty or not) if type=object is not given
+ return d.parseKind(s, path)
+ } else {
+ // Definition has no type and no properties. Treat it as an arbitrary value
+ // TODO(incomplete): what if it has additionalProperties=false or patternProperties?
+ // ANSWER: parseArbitrary is less strict than it has to be with patternProperties (which is ignored). So this is correct (of course not complete).
+ return d.parseArbitrary(s, path)
+ }
+ case 1:
+ t := objectTypes[0]
+ switch t {
+ case object:
+ if s.GetProperties() != nil {
+ return d.parseKind(s, path)
+ } else {
+ return d.parseMap(s, path)
+ }
+ case array:
+ return d.parseArray(s, path)
+ }
+ return d.parsePrimitive(s, path)
+ default:
+ // the OpenAPI generator never generates (nor it ever did in the past) OpenAPI type definitions with multiple types
+ // TODO(wrong): this is rejecting a completely valid OpenAPI spec
+ // TODO(CRD validation schema publishing): filter these out
+ return nil, newSchemaError(path, "definitions with multiple types aren't supported")
+ }
+}
+
+// LookupModel is public through the interface of Models. It
+// returns a visitable schema from the given model name.
+func (d *Definitions) LookupModel(model string) Schema {
+ return d.models[model]
+}
+
+func (d *Definitions) ListModels() []string {
+ models := []string{}
+
+ for model := range d.models {
+ models = append(models, model)
+ }
+
+ sort.Strings(models)
+ return models
+}
+
+type Ref struct {
+ BaseSchema
+
+ reference string
+ definitions *Definitions
+}
+
+var _ Reference = &Ref{}
+
+func (r *Ref) Reference() string {
+ return r.reference
+}
+
+func (r *Ref) SubSchema() Schema {
+ return r.definitions.models[r.reference]
+}
+
+func (r *Ref) Accept(v SchemaVisitor) {
+ v.VisitReference(r)
+}
+
+func (r *Ref) GetName() string {
+ return fmt.Sprintf("Reference to %q", r.reference)
+}
diff --git a/vendor/k8s.io/kube-openapi/pkg/util/proto/openapi.go b/vendor/k8s.io/kube-openapi/pkg/util/proto/openapi.go
new file mode 100644
index 000000000..46643aa50
--- /dev/null
+++ b/vendor/k8s.io/kube-openapi/pkg/util/proto/openapi.go
@@ -0,0 +1,278 @@
+/*
+Copyright 2017 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 proto
+
+import (
+ "fmt"
+ "sort"
+ "strings"
+)
+
+// Defines openapi types.
+const (
+ Integer = "integer"
+ Number = "number"
+ String = "string"
+ Boolean = "boolean"
+
+ // These types are private as they should never leak, and are
+ // represented by actual structs.
+ array = "array"
+ object = "object"
+)
+
+// Models interface describe a model provider. They can give you the
+// schema for a specific model.
+type Models interface {
+ LookupModel(string) Schema
+ ListModels() []string
+}
+
+// SchemaVisitor is an interface that you need to implement if you want
+// to "visit" an openapi schema. A dispatch on the Schema type will call
+// the appropriate function based on its actual type:
+// - Array is a list of one and only one given subtype
+// - Map is a map of string to one and only one given subtype
+// - Primitive can be string, integer, number and boolean.
+// - Kind is an object with specific fields mapping to specific types.
+// - Reference is a link to another definition.
+type SchemaVisitor interface {
+ VisitArray(*Array)
+ VisitMap(*Map)
+ VisitPrimitive(*Primitive)
+ VisitKind(*Kind)
+ VisitReference(Reference)
+}
+
+// SchemaVisitorArbitrary is an additional visitor interface which handles
+// arbitrary types. For backwards compatibility, it's a separate interface
+// which is checked for at runtime.
+type SchemaVisitorArbitrary interface {
+ SchemaVisitor
+ VisitArbitrary(*Arbitrary)
+}
+
+// Schema is the base definition of an openapi type.
+type Schema interface {
+ // Giving a visitor here will let you visit the actual type.
+ Accept(SchemaVisitor)
+
+ // Pretty print the name of the type.
+ GetName() string
+ // Describes how to access this field.
+ GetPath() *Path
+ // Describes the field.
+ GetDescription() string
+ // Returns type extensions.
+ GetExtensions() map[string]interface{}
+}
+
+// Path helps us keep track of type paths
+type Path struct {
+ parent *Path
+ key string
+}
+
+func NewPath(key string) Path {
+ return Path{key: key}
+}
+
+func (p *Path) Get() []string {
+ if p == nil {
+ return []string{}
+ }
+ if p.key == "" {
+ return p.parent.Get()
+ }
+ return append(p.parent.Get(), p.key)
+}
+
+func (p *Path) Len() int {
+ return len(p.Get())
+}
+
+func (p *Path) String() string {
+ return strings.Join(p.Get(), "")
+}
+
+// ArrayPath appends an array index and creates a new path
+func (p *Path) ArrayPath(i int) Path {
+ return Path{
+ parent: p,
+ key: fmt.Sprintf("[%d]", i),
+ }
+}
+
+// FieldPath appends a field name and creates a new path
+func (p *Path) FieldPath(field string) Path {
+ return Path{
+ parent: p,
+ key: fmt.Sprintf(".%s", field),
+ }
+}
+
+// BaseSchema holds data used by each types of schema.
+type BaseSchema struct {
+ Description string
+ Extensions map[string]interface{}
+
+ Path Path
+}
+
+func (b *BaseSchema) GetDescription() string {
+ return b.Description
+}
+
+func (b *BaseSchema) GetExtensions() map[string]interface{} {
+ return b.Extensions
+}
+
+func (b *BaseSchema) GetPath() *Path {
+ return &b.Path
+}
+
+// Array must have all its element of the same `SubType`.
+type Array struct {
+ BaseSchema
+
+ SubType Schema
+}
+
+var _ Schema = &Array{}
+
+func (a *Array) Accept(v SchemaVisitor) {
+ v.VisitArray(a)
+}
+
+func (a *Array) GetName() string {
+ return fmt.Sprintf("Array of %s", a.SubType.GetName())
+}
+
+// Kind is a complex object. It can have multiple different
+// subtypes for each field, as defined in the `Fields` field. Mandatory
+// fields are listed in `RequiredFields`. The key of the object is
+// always of type `string`.
+type Kind struct {
+ BaseSchema
+
+ // Lists names of required fields.
+ RequiredFields []string
+ // Maps field names to types.
+ Fields map[string]Schema
+ // FieldOrder reports the canonical order for the fields.
+ FieldOrder []string
+}
+
+var _ Schema = &Kind{}
+
+func (k *Kind) Accept(v SchemaVisitor) {
+ v.VisitKind(k)
+}
+
+func (k *Kind) GetName() string {
+ properties := []string{}
+ for key := range k.Fields {
+ properties = append(properties, key)
+ }
+ return fmt.Sprintf("Kind(%v)", properties)
+}
+
+// IsRequired returns true if `field` is a required field for this type.
+func (k *Kind) IsRequired(field string) bool {
+ for _, f := range k.RequiredFields {
+ if f == field {
+ return true
+ }
+ }
+ return false
+}
+
+// Keys returns a alphabetically sorted list of keys.
+func (k *Kind) Keys() []string {
+ keys := make([]string, 0)
+ for key := range k.Fields {
+ keys = append(keys, key)
+ }
+ sort.Strings(keys)
+ return keys
+}
+
+// Map is an object who values must all be of the same `SubType`.
+// The key of the object is always of type `string`.
+type Map struct {
+ BaseSchema
+
+ SubType Schema
+}
+
+var _ Schema = &Map{}
+
+func (m *Map) Accept(v SchemaVisitor) {
+ v.VisitMap(m)
+}
+
+func (m *Map) GetName() string {
+ return fmt.Sprintf("Map of %s", m.SubType.GetName())
+}
+
+// Primitive is a literal. There can be multiple types of primitives,
+// and this subtype can be visited through the `subType` field.
+type Primitive struct {
+ BaseSchema
+
+ // Type of a primitive must be one of: integer, number, string, boolean.
+ Type string
+ Format string
+}
+
+var _ Schema = &Primitive{}
+
+func (p *Primitive) Accept(v SchemaVisitor) {
+ v.VisitPrimitive(p)
+}
+
+func (p *Primitive) GetName() string {
+ if p.Format == "" {
+ return p.Type
+ }
+ return fmt.Sprintf("%s (%s)", p.Type, p.Format)
+}
+
+// Arbitrary is a value of any type (primitive, object or array)
+type Arbitrary struct {
+ BaseSchema
+}
+
+var _ Schema = &Arbitrary{}
+
+func (a *Arbitrary) Accept(v SchemaVisitor) {
+ if visitor, ok := v.(SchemaVisitorArbitrary); ok {
+ visitor.VisitArbitrary(a)
+ }
+}
+
+func (a *Arbitrary) GetName() string {
+ return "Arbitrary value (primitive, object or array)"
+}
+
+// Reference implementation depends on the type of document.
+type Reference interface {
+ Schema
+
+ Reference() string
+ SubSchema() Schema
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 38e556f6f..803dffd2c 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -4,6 +4,8 @@ github.com/blang/semver
github.com/davecgh/go-spew/spew
# github.com/dyatlov/go-opengraph v0.0.0-20180429202543-816b6608b3c8
github.com/dyatlov/go-opengraph/opengraph
+# github.com/evanphx/json-patch v4.2.0+incompatible
+github.com/evanphx/json-patch
# github.com/fsnotify/fsnotify v1.4.7
github.com/fsnotify/fsnotify
# github.com/go-ldap/ldap v3.0.3+incompatible
@@ -66,8 +68,11 @@ github.com/nicksnyder/go-i18n/i18n
github.com/nicksnyder/go-i18n/i18n/bundle
github.com/nicksnyder/go-i18n/i18n/language
github.com/nicksnyder/go-i18n/i18n/translation
-# github.com/nlopes/slack v0.4.0
+# github.com/nlopes/slack v0.5.1-0.20190623232825-2891986e2a3e
github.com/nlopes/slack
+github.com/nlopes/slack/slacktest
+github.com/nlopes/slack/internal/errorsx
+github.com/nlopes/slack/internal/timex
github.com/nlopes/slack/slackutilsx
# github.com/olivere/elastic v6.2.21+incompatible
github.com/olivere/elastic
@@ -79,10 +84,14 @@ github.com/pborman/uuid
github.com/pelletier/go-toml
# github.com/pkg/errors v0.8.1
github.com/pkg/errors
+# github.com/pmezard/go-difflib v1.0.0
+github.com/pmezard/go-difflib/difflib
# github.com/sirupsen/logrus v1.4.2
github.com/sirupsen/logrus
# github.com/spf13/pflag v1.0.3
github.com/spf13/pflag
+# github.com/stretchr/testify v1.3.0
+github.com/stretchr/testify/assert
# go.uber.org/atomic v1.4.0
go.uber.org/atomic
# go.uber.org/multierr v1.1.0
@@ -149,11 +158,11 @@ gopkg.in/natefinch/lumberjack.v2
gopkg.in/yaml.v2
# k8s.io/api v0.0.0-20190802020852-fde72677e822
k8s.io/api/core/v1
-k8s.io/api/apps/v1beta1
+k8s.io/api/apps/v1
k8s.io/api/batch/v1
k8s.io/api/extensions/v1beta1
k8s.io/api/rbac/v1
-k8s.io/api/apps/v1
+k8s.io/api/apps/v1beta1
k8s.io/api/admissionregistration/v1beta1
k8s.io/api/apps/v1beta2
k8s.io/api/auditregistration/v1alpha1
@@ -186,9 +195,10 @@ k8s.io/api/authorization/v1
k8s.io/api/authorization/v1beta1
# k8s.io/apimachinery v0.0.0-20190731142807-035e418f1ad9
k8s.io/apimachinery/pkg/apis/meta/v1
-k8s.io/apimachinery/pkg/api/resource
+k8s.io/apimachinery/pkg/apis/meta/v1/unstructured
k8s.io/apimachinery/pkg/runtime
k8s.io/apimachinery/pkg/runtime/schema
+k8s.io/apimachinery/pkg/api/resource
k8s.io/apimachinery/pkg/types
k8s.io/apimachinery/pkg/util/intstr
k8s.io/apimachinery/pkg/api/errors
@@ -209,27 +219,31 @@ k8s.io/apimachinery/pkg/runtime/serializer/streaming
k8s.io/apimachinery/pkg/util/net
k8s.io/apimachinery/pkg/util/errors
k8s.io/apimachinery/pkg/util/validation
-k8s.io/apimachinery/pkg/conversion/queryparams
+k8s.io/apimachinery/pkg/runtime/serializer
k8s.io/apimachinery/pkg/util/json
+k8s.io/apimachinery/pkg/conversion/queryparams
k8s.io/apimachinery/pkg/util/validation/field
k8s.io/apimachinery/pkg/apis/meta/internalversion
k8s.io/apimachinery/third_party/forked/golang/reflect
-k8s.io/apimachinery/pkg/runtime/serializer
k8s.io/apimachinery/pkg/version
k8s.io/apimachinery/pkg/runtime/serializer/json
k8s.io/apimachinery/pkg/runtime/serializer/versioning
-k8s.io/apimachinery/pkg/apis/meta/v1beta1
k8s.io/apimachinery/pkg/runtime/serializer/protobuf
k8s.io/apimachinery/pkg/runtime/serializer/recognizer
+k8s.io/apimachinery/pkg/util/strategicpatch
+k8s.io/apimachinery/pkg/apis/meta/v1beta1
k8s.io/apimachinery/pkg/util/framer
k8s.io/apimachinery/pkg/util/yaml
-k8s.io/apimachinery/pkg/apis/meta/v1/unstructured
+k8s.io/apimachinery/pkg/util/mergepatch
+k8s.io/apimachinery/third_party/forked/golang/json
# k8s.io/client-go v0.0.0-20190620085101-78d2af792bab
k8s.io/client-go/tools/cache
k8s.io/client-go/informers
k8s.io/client-go/kubernetes
k8s.io/client-go/rest
k8s.io/client-go/tools/clientcmd
+k8s.io/client-go/kubernetes/fake
+k8s.io/client-go/dynamic/fake
k8s.io/client-go/tools/pager
k8s.io/client-go/util/retry
k8s.io/client-go/informers/admissionregistration
@@ -298,6 +312,45 @@ k8s.io/client-go/util/cert
k8s.io/client-go/tools/auth
k8s.io/client-go/tools/clientcmd/api/latest
k8s.io/client-go/util/homedir
+k8s.io/client-go/discovery/fake
+k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake
+k8s.io/client-go/kubernetes/typed/apps/v1/fake
+k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake
+k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake
+k8s.io/client-go/kubernetes/typed/auditregistration/v1alpha1/fake
+k8s.io/client-go/kubernetes/typed/authentication/v1/fake
+k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake
+k8s.io/client-go/kubernetes/typed/authorization/v1/fake
+k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake
+k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake
+k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake
+k8s.io/client-go/kubernetes/typed/autoscaling/v2beta2/fake
+k8s.io/client-go/kubernetes/typed/batch/v1/fake
+k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake
+k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake
+k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake
+k8s.io/client-go/kubernetes/typed/coordination/v1/fake
+k8s.io/client-go/kubernetes/typed/coordination/v1beta1/fake
+k8s.io/client-go/kubernetes/typed/core/v1/fake
+k8s.io/client-go/kubernetes/typed/events/v1beta1/fake
+k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake
+k8s.io/client-go/kubernetes/typed/networking/v1/fake
+k8s.io/client-go/kubernetes/typed/networking/v1beta1/fake
+k8s.io/client-go/kubernetes/typed/node/v1alpha1/fake
+k8s.io/client-go/kubernetes/typed/node/v1beta1/fake
+k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake
+k8s.io/client-go/kubernetes/typed/rbac/v1/fake
+k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake
+k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake
+k8s.io/client-go/kubernetes/typed/scheduling/v1/fake
+k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake
+k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake
+k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake
+k8s.io/client-go/kubernetes/typed/storage/v1/fake
+k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake
+k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake
+k8s.io/client-go/testing
+k8s.io/client-go/dynamic
k8s.io/client-go/informers/admissionregistration/v1beta1
k8s.io/client-go/informers/apps/v1
k8s.io/client-go/informers/apps/v1beta1
@@ -372,6 +425,8 @@ k8s.io/client-go/listers/storage/v1alpha1
k8s.io/client-go/listers/storage/v1beta1
# k8s.io/klog v0.3.3
k8s.io/klog
+# k8s.io/kube-openapi v0.0.0-20190709113604-33be087ad058
+k8s.io/kube-openapi/pkg/util/proto
# k8s.io/utils v0.0.0-20190801114015-581e00157fb1
k8s.io/utils/buffer
k8s.io/utils/trace