Merge pull request #126 from glower/hipchat-approve-bot

move slack related bot code to a sub module
pull/128/head
Karolis Rusenas 2017-12-21 10:26:52 +00:00 committed by GitHub
commit 9a8f8090c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
71 changed files with 14957 additions and 1166 deletions

View File

@ -1,15 +1,7 @@
package bot
import (
"context"
"encoding/json"
"errors"
"fmt"
"strconv"
"strings"
"time"
"github.com/nlopes/slack"
"sync"
"github.com/keel-hq/keel/approvals"
"github.com/keel-hq/keel/provider/kubernetes"
@ -19,11 +11,11 @@ import (
)
const (
removeApprovalPrefix = "rm approval"
RemoveApprovalPrefix = "rm approval"
)
var (
botEventTextToResponse = map[string][]string{
BotEventTextToResponse = map[string][]string{
"help": {
`Here's a list of supported commands`,
`- "get deployments" -> get a list of all deployments`,
@ -37,323 +29,79 @@ var (
}
// static bot commands can be used straight away
staticBotCommands = map[string]bool{
StaticBotCommands = map[string]bool{
"get deployments": true,
"get approvals": true,
}
// dynamic bot command prefixes have to be matched
dynamicBotCommandPrefixes = []string{removeApprovalPrefix}
DynamicBotCommandPrefixes = []string{RemoveApprovalPrefix}
approvalResponseKeyword = "approve"
rejectResponseKeyword = "reject"
ApprovalResponseKeyword = "approve"
RejectResponseKeyword = "reject"
)
// SlackImplementer - implementes slack HTTP functionality, used to
// send messages with attachments
type SlackImplementer interface {
PostMessage(channel, text string, params slack.PostMessageParameters) (string, string, error)
type Bot interface {
Run(k8sImplementer kubernetes.Implementer, approvalsManager approvals.Manager) (teardown func(), err error)
}
// approvalResponse - used to track approvals once vote begins
type approvalResponse struct {
type BotFactory func(k8sImplementer kubernetes.Implementer, approvalsManager approvals.Manager) (teardown func(), err error)
type teardown func()
var (
botsM sync.RWMutex
bots = make(map[string]BotFactory)
teardowns = make(map[string]teardown)
)
// ApprovalResponse - used to track approvals once vote begins
type ApprovalResponse struct {
User string
Status types.ApprovalStatus
Text string
}
// Bot - main slack bot container
type Bot struct {
id string // bot id
name string // bot name
users map[string]string
msgPrefix string
slackClient *slack.Client
slackRTM *slack.RTM
slackHTTPClient SlackImplementer
approvalsRespCh chan *approvalResponse
approvalsManager approvals.Manager
approvalsChannel string // slack approvals channel name
k8sImplementer kubernetes.Implementer
ctx context.Context
}
// New - create new bot instance
func New(name, token, approvalsChannel string, k8sImplementer kubernetes.Implementer, approvalsManager approvals.Manager) *Bot {
client := slack.New(token)
bot := &Bot{
slackClient: client,
slackHTTPClient: client,
k8sImplementer: k8sImplementer,
name: name,
approvalsManager: approvalsManager,
approvalsChannel: approvalsChannel,
approvalsRespCh: make(chan *approvalResponse), // don't add buffer to make it blocking
// RegisterBot makes a BotRunner available by the provided name.
func RegisterBot(name string, b BotFactory) {
if name == "" {
panic("bot: could not register a BotFactory with an empty name")
}
return bot
}
// Start - start bot
func (b *Bot) Start(ctx context.Context) error {
// setting root context
b.ctx = ctx
users, err := b.slackClient.GetUsers()
if err != nil {
return err
if b == nil {
panic("bot: could not register a nil BotFactory")
}
b.users = map[string]string{}
botsM.Lock()
defer botsM.Unlock()
for _, user := range users {
switch user.Name {
case b.name:
if user.IsBot {
b.id = user.ID
}
default:
continue
}
}
if b.id == "" {
return errors.New("could not find bot in the list of names, check if the bot is called \"" + b.name + "\" ")
}
b.msgPrefix = strings.ToLower("<@" + b.id + ">")
// processing messages coming from slack RTM client
go b.startInternal()
// processing slack approval responses
go b.processApprovalResponses()
// subscribing for approval requests
go b.subscribeForApprovals()
return nil
}
func (b *Bot) startInternal() error {
b.slackRTM = b.slackClient.NewRTM()
go b.slackRTM.ManageConnection()
for {
select {
case <-b.ctx.Done():
return nil
case msg := <-b.slackRTM.IncomingEvents:
switch ev := msg.Data.(type) {
case *slack.HelloEvent:
// Ignore hello
case *slack.ConnectedEvent:
// fmt.Println("Infos:", ev.Info)
// fmt.Println("Connection counter:", ev.ConnectionCount)
// Replace #general with your Channel ID
// b.slackRTM.SendMessage(b.slackRTM.NewOutgoingMessage("Hello world", "#general"))
case *slack.MessageEvent:
b.handleMessage(ev)
case *slack.PresenceChangeEvent:
// fmt.Printf("Presence Change: %v\n", ev)
// case *slack.LatencyReport:
// fmt.Printf("Current latency: %v\n", ev.Value)
case *slack.RTMError:
fmt.Printf("Error: %s\n", ev.Error())
case *slack.InvalidAuthEvent:
fmt.Printf("Invalid credentials")
return fmt.Errorf("invalid credentials")
default:
// Ignore other events..
// fmt.Printf("Unexpected: %v\n", msg.Data)
}
}
}
}
func (b *Bot) postMessage(title, message, color string, fields []slack.AttachmentField) error {
params := slack.NewPostMessageParameters()
params.Username = b.name
params.Attachments = []slack.Attachment{
slack.Attachment{
Fallback: message,
Color: color,
Fields: fields,
Footer: "https://keel.sh",
Ts: json.Number(strconv.Itoa(int(time.Now().Unix()))),
},
}
_, _, err := b.slackHTTPClient.PostMessage(b.approvalsChannel, "", params)
if err != nil {
log.WithFields(log.Fields{
"error": err,
}).Error("bot.postMessage: failed to send message")
}
return err
}
func (b *Bot) isApproval(event *slack.MessageEvent, eventText string) (resp *approvalResponse, ok bool) {
if strings.HasPrefix(strings.ToLower(eventText), approvalResponseKeyword) {
return &approvalResponse{
User: event.User,
Status: types.ApprovalStatusApproved,
Text: eventText,
}, true
}
if strings.HasPrefix(strings.ToLower(eventText), rejectResponseKeyword) {
return &approvalResponse{
User: event.User,
Status: types.ApprovalStatusRejected,
Text: eventText,
}, true
}
return nil, false
}
// TODO(k): cache results in a map or get this info on startup. Although
// if channel was then recreated (unlikely), we would miss results
func (b *Bot) isApprovalsChannel(event *slack.MessageEvent) bool {
for _, ch := range b.slackRTM.GetInfo().Channels {
if ch.ID == event.Channel && ch.Name == b.approvalsChannel {
return true
}
}
return false
}
func (b *Bot) handleMessage(event *slack.MessageEvent) {
if event.BotID != "" || event.User == "" || event.SubType == "bot_message" {
log.WithFields(log.Fields{
"event_bot_ID": event.BotID,
"event_user": event.User,
"event_subtype": event.SubType,
}).Info("handleMessage: ignoring message")
return
}
eventText := strings.Trim(strings.ToLower(event.Text), " \n\r")
if !b.isBotMessage(event, eventText) {
return
}
eventText = b.trimBot(eventText)
// only accepting approvals from approvals channel
if b.isApprovalsChannel(event) {
approval, ok := b.isApproval(event, eventText)
if ok {
b.approvalsRespCh <- approval
return
}
}
// Responses that are just a canned string response
if responseLines, ok := botEventTextToResponse[eventText]; ok {
response := strings.Join(responseLines, "\n")
b.respond(event, formatAsSnippet(response))
return
}
if b.isCommand(event, eventText) {
b.handleCommand(event, eventText)
return
if _, dup := bots[name]; dup {
panic("bot: RegisterBot called twice for " + name)
}
log.WithFields(log.Fields{
"name": b.name,
"bot_id": b.id,
"command": eventText,
"untrimmed": strings.Trim(strings.ToLower(event.Text), " \n\r"),
}).Debug("handleMessage: bot couldn't recognise command")
"name": name,
}).Info("bot: registered")
bots[name] = b
}
func (b *Bot) isCommand(event *slack.MessageEvent, eventText string) bool {
if staticBotCommands[eventText] {
return true
}
for _, prefix := range dynamicBotCommandPrefixes {
if strings.HasPrefix(eventText, prefix) {
return true
func Run(k8sImplementer kubernetes.Implementer, approvalsManager approvals.Manager) {
for botName, runner := range bots {
teardownBot, err := runner(k8sImplementer, approvalsManager)
if err != nil {
log.WithFields(log.Fields{
"error": err,
}).Fatalf("main: failed to setup %s bot\n", botName)
} else {
log.Debugf(">>> Run [%s] bot", botName)
teardowns[botName] = teardownBot
}
}
return false
}
func (b *Bot) handleCommand(event *slack.MessageEvent, eventText string) {
switch eventText {
case "get deployments":
log.Info("getting deployments")
response := b.deploymentsResponse(Filter{})
b.respond(event, formatAsSnippet(response))
return
case "get approvals":
response := b.approvalsResponse()
b.respond(event, formatAsSnippet(response))
return
func Stop() {
for botName, teardown := range teardowns {
log.Infof("Teardown %s bot\n", botName)
teardown()
}
// handle dynamic commands
if strings.HasPrefix(eventText, removeApprovalPrefix) {
b.respond(event, formatAsSnippet(b.removeApprovalHandler(strings.TrimSpace(strings.TrimPrefix(eventText, removeApprovalPrefix)))))
return
}
log.Info("command not found")
}
func (b *Bot) respond(event *slack.MessageEvent, response string) {
b.slackRTM.SendMessage(b.slackRTM.NewOutgoingMessage(response, event.Channel))
}
func (b *Bot) isBotMessage(event *slack.MessageEvent, eventText string) bool {
prefixes := []string{
b.msgPrefix,
"keel",
}
for _, p := range prefixes {
if strings.HasPrefix(eventText, p) {
return true
}
}
// Direct message channels always starts with 'D'
return strings.HasPrefix(event.Channel, "D")
}
func (b *Bot) trimBot(msg string) string {
msg = strings.Replace(msg, strings.ToLower(b.msgPrefix), "", 1)
msg = strings.TrimPrefix(msg, b.name)
msg = strings.Trim(msg, " :\n")
return msg
}
func formatAsSnippet(response string) string {
return "```" + response + "```"
}

267
bot/hipchat/approvals.go Normal file
View File

@ -0,0 +1,267 @@
package hipchat
import (
"bytes"
"fmt"
"strings"
"github.com/keel-hq/keel/bot"
"github.com/keel-hq/keel/bot/formatter"
"github.com/keel-hq/keel/types"
log "github.com/Sirupsen/logrus"
)
func (b *Bot) subscribeForApprovals() error {
log.Debugf(">>> hipchat.subscribeForApprovals()\n")
approvalsCh, err := b.approvalsManager.Subscribe(b.ctx)
if err != nil {
log.Debugf(">>> [ERROR] hipchat.subscribeForApprovals(): %s\n", err.Error())
return err
}
for {
select {
case <-b.ctx.Done():
return nil
case a := <-approvalsCh:
err = b.requestApproval(a)
if err != nil {
log.WithFields(log.Fields{
"error": err,
"approval": a.Identifier,
}).Error("bot.subscribeForApprovals: approval request failed")
}
}
}
}
// Request - request approval
func (b *Bot) requestApproval(req *types.Approval) error {
msg := fmt.Sprintf(`Approval required!
%s
To vote for change type '%s approve %s'
To reject it: '%s reject %s'
Votes: %d/%d
Delta: %s
Identifier: %s
Provider: %s`,
req.Message, b.mentionName, req.Identifier, b.mentionName, req.Identifier,
req.VotesReceived, req.VotesRequired, req.Delta(), req.Identifier,
req.Provider.String())
return b.postMessage(msg)
}
func (b *Bot) processApprovalResponses() error {
for {
select {
case <-b.ctx.Done():
return nil
case resp := <-b.approvalsRespCh:
switch resp.Status {
case types.ApprovalStatusApproved:
err := b.processApprovedResponse(resp)
if err != nil {
log.WithFields(log.Fields{
"error": err,
}).Error("bot.processApprovalResponses: failed to process approval response message")
}
case types.ApprovalStatusRejected:
err := b.processRejectedResponse(resp)
if err != nil {
log.WithFields(log.Fields{
"error": err,
}).Error("bot.processApprovalResponses: failed to process approval reject response message")
}
}
}
}
}
func (b *Bot) processApprovedResponse(approvalResponse *bot.ApprovalResponse) error {
trimmed := strings.TrimPrefix(approvalResponse.Text, bot.ApprovalResponseKeyword)
identifiers := strings.Split(trimmed, " ")
if len(identifiers) == 0 {
return nil
}
for _, identifier := range identifiers {
if identifier == "" {
continue
}
approval, err := b.approvalsManager.Approve(identifier, approvalResponse.User)
if err != nil {
log.WithFields(log.Fields{
"error": err,
"identifier": identifier,
}).Error("bot.processApprovedResponse: failed to approve")
continue
}
err = b.replyToApproval(approval)
if err != nil {
log.WithFields(log.Fields{
"error": err,
"identifier": identifier,
}).Error("bot.processApprovedResponse: got error while replying after processing approved approval")
}
}
return nil
}
func (b *Bot) processRejectedResponse(approvalResponse *bot.ApprovalResponse) error {
trimmed := strings.TrimPrefix(approvalResponse.Text, bot.RejectResponseKeyword)
identifiers := strings.Split(trimmed, " ")
if len(identifiers) == 0 {
return nil
}
for _, identifier := range identifiers {
approval, err := b.approvalsManager.Reject(identifier)
if err != nil {
log.WithFields(log.Fields{
"error": err,
"identifier": identifier,
}).Error("bot.processApprovedResponse: failed to reject")
continue
}
err = b.replyToApproval(approval)
if err != nil {
log.WithFields(log.Fields{
"error": err,
"identifier": identifier,
}).Error("bot.processApprovedResponse: got error while replying after processing rejected approval")
}
}
return nil
}
func (b *Bot) replyToApproval(approval *types.Approval) error {
switch approval.Status() {
case types.ApprovalStatusPending:
b.postMessage("Vote received")
// "Vote received",
// "All approvals received, thanks for voting!",
// types.LevelInfo.Color(),
// []slack.AttachmentField{
// slack.AttachmentField{
// Title: "vote received!",
// Value: "Waiting for remaining votes.",
// Short: false,
// },
// slack.AttachmentField{
// Title: "Votes",
// Value: fmt.Sprintf("%d/%d", approval.VotesReceived, approval.VotesRequired),
// Short: true,
// },
// slack.AttachmentField{
// Title: "Delta",
// Value: approval.Delta(),
// Short: true,
// },
// slack.AttachmentField{
// Title: "Identifier",
// Value: approval.Identifier,
// Short: true,
// },
// })
case types.ApprovalStatusRejected:
b.postMessage("Change rejected")
// "Change rejected",
// "Change was rejected",
// types.LevelWarn.Color(),
// []slack.AttachmentField{
// slack.AttachmentField{
// Title: "change rejected",
// Value: "Change was rejected.",
// Short: false,
// },
// slack.AttachmentField{
// Title: "Status",
// Value: approval.Status().String(),
// Short: true,
// },
// slack.AttachmentField{
// Title: "Votes",
// Value: fmt.Sprintf("%d/%d", approval.VotesReceived, approval.VotesRequired),
// Short: true,
// },
// slack.AttachmentField{
// Title: "Delta",
// Value: approval.Delta(),
// Short: true,
// },
// slack.AttachmentField{
// Title: "Identifier",
// Value: approval.Identifier,
// Short: true,
// },
// })
case types.ApprovalStatusApproved:
b.postMessage("approval received")
// "approval received",
// "All approvals received, thanks for voting!",
// types.LevelSuccess.Color(),
// []slack.AttachmentField{
// slack.AttachmentField{
// Title: "update approved!",
// Value: "All approvals received, thanks for voting!",
// Short: false,
// },
// slack.AttachmentField{
// Title: "Votes",
// Value: fmt.Sprintf("%d/%d", approval.VotesReceived, approval.VotesRequired),
// Short: true,
// },
// slack.AttachmentField{
// Title: "Delta",
// Value: approval.Delta(),
// Short: true,
// },
// slack.AttachmentField{
// Title: "Identifier",
// Value: approval.Identifier,
// Short: true,
// },
// })
}
return nil
}
func (b *Bot) approvalsResponse() string {
approvals, err := b.approvalsManager.List()
if err != nil {
return fmt.Sprintf("got error while fetching approvals: %s", err)
}
if len(approvals) == 0 {
return fmt.Sprintf("there are currently no request waiting to be approved.")
}
buf := &bytes.Buffer{}
approvalCtx := formatter.Context{
Output: buf,
Format: formatter.NewApprovalsFormat(formatter.TableFormatKey, false),
}
err = formatter.ApprovalWrite(approvalCtx, approvals)
if err != nil {
return fmt.Sprintf("got error while formatting approvals: %s", err)
}
return buf.String()
}
func (b *Bot) removeApprovalHandler(identifier string) string {
err := b.approvalsManager.Delete(identifier)
if err != nil {
return fmt.Sprintf("failed to remove '%s' approval: %s.", identifier, err)
}
return fmt.Sprintf("approval '%s' removed.", identifier)
}

327
bot/hipchat/hipchat.go Normal file
View File

@ -0,0 +1,327 @@
package hipchat
import (
"context"
"errors"
"fmt"
"os"
"regexp"
"strings"
"time"
"github.com/keel-hq/keel/approvals"
"github.com/keel-hq/keel/bot"
"github.com/keel-hq/keel/constants"
"github.com/keel-hq/keel/provider/kubernetes"
"github.com/keel-hq/keel/types"
log "github.com/Sirupsen/logrus"
"github.com/daneharrigan/hipchat"
)
// Bot - main hipchat bot container
type Bot struct {
id string // bot id
name string // bot name
mentionName string
userName string // bot user name
password string // bot user password
users map[string]string
msgPrefix string
hipchatClient *hipchat.Client
approvalsRespCh chan *bot.ApprovalResponse
approvalsManager approvals.Manager
approvalsChannel string // hipchat approvals channel name
k8sImplementer kubernetes.Implementer
ctx context.Context
}
func init() {
bot.RegisterBot("hipchat", Run)
}
// Run ...
func Run(k8sImplementer kubernetes.Implementer, approvalsManager approvals.Manager) (teardown func(), err error) {
if os.Getenv(constants.EnvHipchatApprovalsPasswort) != "" {
botName := "keel"
if os.Getenv(constants.EnvHipchatApprovalsBotName) != "" {
botName = os.Getenv(constants.EnvHipchatApprovalsBotName)
}
botUserName := ""
if os.Getenv(constants.EnvHipchatApprovalsUserName) != "" { // need this!!!!
botUserName = os.Getenv(constants.EnvHipchatApprovalsUserName)
}
pass := os.Getenv(constants.EnvHipchatApprovalsPasswort)
approvalsChannel := "general"
if os.Getenv(constants.EnvHipchatApprovalsChannel) != "" {
approvalsChannel = os.Getenv(constants.EnvHipchatApprovalsChannel)
}
bot := new(botName, botUserName, pass, approvalsChannel, k8sImplementer, approvalsManager)
ctx, cancel := context.WithCancel(context.Background())
err := bot.Start(ctx)
if err != nil {
cancel()
return nil, err
}
teardown := func() {
// cancelling context
cancel()
}
return teardown, nil
}
return func() {}, nil
}
//--------------------- <XMPP client> -------------------------------------
func connect(username, password string) *hipchat.Client {
log.Debugf(">>> bot.hipchat.NewClient(): user=%s, pass=%s\n", username, password)
attempts := 10
for {
log.Debugf(">>> try to connect to hipchat")
client, err := hipchat.NewClient(username, password, "bot", "plain")
// could not authenticate
if err != nil {
log.Errorf("bot.hipchat.connect: Error=%s\n", err)
if err.Error() == "could not authenticate" {
return nil
}
}
if attempts == 0 {
return nil
}
if client != nil && err == nil {
return client
}
log.Debugf("wait fo 30 seconds")
time.Sleep(30 * time.Second)
attempts--
}
}
//--------------------- </XMPP client> -------------------------------------
func new(name, username, pass, approvalsChannel string, k8sImplementer kubernetes.Implementer, approvalsManager approvals.Manager) *Bot {
client := connect(username, pass)
bot := &Bot{
hipchatClient: client,
k8sImplementer: k8sImplementer,
name: name,
mentionName: "@" + strings.Replace(name, " ", "", -1),
approvalsManager: approvalsManager,
approvalsChannel: approvalsChannel, // roomJid
approvalsRespCh: make(chan *bot.ApprovalResponse), // don't add buffer to make it blocking
}
return bot
}
// Start the bot
func (b *Bot) Start(ctx context.Context) error {
log.Debugln(">>> bot.hipchat.Start()")
if b.hipchatClient == nil {
return errors.New("could not conect to hipchat server")
}
// setting root context
b.ctx = ctx
// processing messages coming from slack RTM client
go b.startInternal()
// processing slack approval responses
go b.processApprovalResponses()
// subscribing for approval requests
go b.subscribeForApprovals()
return nil
}
func (b *Bot) startInternal() error {
client := b.hipchatClient
log.Debugf("startInternal(): channel=%s, userName=%s\n", b.approvalsChannel, b.name)
client.Status("chat") // chat, away or idle
client.Join(b.approvalsChannel, b.name)
go client.KeepAlive()
go func() {
for {
select {
case message := <-client.Messages():
b.handleMessage(message)
}
}
}()
return nil
}
// // A Message represents a message received from HipChat.
// type Message struct {
// From string
// To string
// Body string
// MentionName string
// }
// Body:"@IgorKomlew release notification from keel"
// hipchat.handleMessage(): &hipchat.Message{From:"701032_keel-bot@conf.hipchat.com", To:"701032_4966430@chat.hipchat.com/bot", Body:"release notification from keel", MentionName:""}
func (b *Bot) handleMessage(message *hipchat.Message) {
msg := b.trimXMPPMessage(message)
log.Debugf("hipchat.handleMessage(): %#v // %#v\n", message, msg)
if msg.From == "" || msg.To == "" {
log.Debugf("hipchat.handleMessage(): ignore")
return
}
if !b.isBotMessage(msg) {
log.Debugf("hipchat.handleMessage(): is not a bot message")
return
}
approval, ok := b.isApproval(msg)
if ok {
b.approvalsRespCh <- approval
return
}
if responseLines, ok := bot.BotEventTextToResponse[msg.Body]; ok {
response := strings.Join(responseLines, "\n")
fmt.Println(">>> " + response)
b.respond(response)
return
}
if b.isCommand(msg) {
b.handleCommand(msg)
return
}
log.WithFields(log.Fields{
"name": b.name,
"bot_id": b.id,
"command": msg.Body,
"untrimmed": message.Body,
}).Debug("handleMessage: bot couldn't recognise command")
}
func (b *Bot) respond(response string) {
b.hipchatClient.Say(b.approvalsChannel, b.name, response)
}
func (b *Bot) handleCommand(message *hipchat.Message) {
fmt.Printf("bot.hipchat.handleCommand() %v\n", message)
}
func (b *Bot) isCommand(message *hipchat.Message) bool {
fmt.Printf("bot.hipchat.isCommand=%s\n", message.Body)
if bot.StaticBotCommands[message.Body] {
return true
}
for _, prefix := range bot.DynamicBotCommandPrefixes {
if strings.HasPrefix(message.Body, prefix) {
return true
}
}
return false
}
func (b *Bot) trimXMPPMessage(message *hipchat.Message) *hipchat.Message {
msg := hipchat.Message{}
msg.MentionName = trimMentionName(message.Body)
msg.Body = b.trimBot(message.Body)
msg.From = b.trimUser(message.From)
msg.To = b.trimUser(message.To)
return &msg
}
func trimMentionName(message string) string {
re := regexp.MustCompile(`^(@\w+)`)
match := re.FindStringSubmatch(message)
if match == nil {
return ""
}
if len(match) != 0 {
return match[1]
}
return ""
}
func (b *Bot) trimUser(user string) string {
re := regexp.MustCompile("/(.*?)$")
match := re.FindStringSubmatch(user)
if match == nil {
return ""
}
if len(match) != 0 {
return match[1]
}
return ""
}
func (b *Bot) postMessage(msg string) error {
log.Debugf(">>> bot.hipchat.postMessage: %s\n", msg)
b.hipchatClient.Say(b.approvalsChannel, b.name, msg)
// b.respond(msg)
return nil
}
func (b *Bot) trimBot(msg string) string {
// msg = strings.Replace(msg, strings.ToLower(b.msgPrefix), "", 1)
msg = strings.TrimPrefix(msg, b.mentionName)
msg = strings.Trim(msg, "\n")
msg = strings.TrimSpace(msg)
return strings.ToLower(msg)
}
func (b *Bot) isApproval(message *hipchat.Message) (resp *bot.ApprovalResponse, ok bool) {
if strings.HasPrefix(message.Body, bot.ApprovalResponseKeyword) {
return &bot.ApprovalResponse{
User: message.From,
Status: types.ApprovalStatusApproved,
Text: message.Body,
}, true
}
if strings.HasPrefix(message.Body, bot.RejectResponseKeyword) {
return &bot.ApprovalResponse{
User: message.From,
Status: types.ApprovalStatusRejected,
Text: message.Body,
}, true
}
return nil, false
}
func (b *Bot) isBotMessage(message *hipchat.Message) bool {
if message.MentionName == b.mentionName {
return true
}
return false
}

View File

@ -1,13 +1,14 @@
package bot
package slack
import (
"bytes"
"fmt"
"strings"
"github.com/nlopes/slack"
"github.com/keel-hq/keel/bot"
"github.com/keel-hq/keel/bot/formatter"
"github.com/keel-hq/keel/types"
"github.com/nlopes/slack"
log "github.com/Sirupsen/logrus"
)
@ -99,8 +100,8 @@ func (b *Bot) processApprovalResponses() error {
}
}
func (b *Bot) processApprovedResponse(approvalResponse *approvalResponse) error {
trimmed := strings.TrimPrefix(approvalResponse.Text, approvalResponseKeyword)
func (b *Bot) processApprovedResponse(approvalResponse *bot.ApprovalResponse) error {
trimmed := strings.TrimPrefix(approvalResponse.Text, bot.ApprovalResponseKeyword)
identifiers := strings.Split(trimmed, " ")
if len(identifiers) == 0 {
return nil
@ -131,8 +132,8 @@ func (b *Bot) processApprovedResponse(approvalResponse *approvalResponse) error
return nil
}
func (b *Bot) processRejectedResponse(approvalResponse *approvalResponse) error {
trimmed := strings.TrimPrefix(approvalResponse.Text, rejectResponseKeyword)
func (b *Bot) processRejectedResponse(approvalResponse *bot.ApprovalResponse) error {
trimmed := strings.TrimPrefix(approvalResponse.Text, bot.RejectResponseKeyword)
identifiers := strings.Split(trimmed, " ")
if len(identifiers) == 0 {
return nil

View File

@ -1,4 +1,4 @@
package bot
package slack
import (
"bytes"

363
bot/slack/slack.go Normal file
View File

@ -0,0 +1,363 @@
package slack
import (
"context"
"encoding/json"
"errors"
"fmt"
"os"
"strconv"
"strings"
"time"
"github.com/nlopes/slack"
"github.com/keel-hq/keel/approvals"
"github.com/keel-hq/keel/bot"
"github.com/keel-hq/keel/constants"
"github.com/keel-hq/keel/provider/kubernetes"
"github.com/keel-hq/keel/types"
log "github.com/Sirupsen/logrus"
)
// SlackImplementer - implementes slack HTTP functionality, used to
// send messages with attachments
type SlackImplementer interface {
PostMessage(channel, text string, params slack.PostMessageParameters) (string, string, error)
}
// Bot - main slack bot container
type Bot struct {
id string // bot id
name string // bot name
users map[string]string
msgPrefix string
slackClient *slack.Client
slackRTM *slack.RTM
slackHTTPClient SlackImplementer
approvalsRespCh chan *bot.ApprovalResponse
approvalsManager approvals.Manager
approvalsChannel string // slack approvals channel name
k8sImplementer kubernetes.Implementer
ctx context.Context
}
func init() {
bot.RegisterBot("slack", Run)
}
func Run(k8sImplementer kubernetes.Implementer, approvalsManager approvals.Manager) (teardown func(), err error) {
if os.Getenv(constants.EnvSlackToken) != "" {
botName := "keel"
if os.Getenv(constants.EnvSlackBotName) != "" {
botName = os.Getenv(constants.EnvSlackBotName)
}
token := os.Getenv(constants.EnvSlackToken)
approvalsChannel := "general"
if os.Getenv(constants.EnvSlackApprovalsChannel) != "" {
approvalsChannel = os.Getenv(constants.EnvSlackApprovalsChannel)
}
slackBot := New(botName, token, approvalsChannel, k8sImplementer, approvalsManager)
ctx, cancel := context.WithCancel(context.Background())
err := slackBot.Start(ctx)
if err != nil {
cancel()
return nil, err
}
teardown := func() {
// cancelling context
cancel()
}
return teardown, nil
}
return func() {}, nil
}
// New - create new bot instance
func New(name, token, approvalsChannel string, k8sImplementer kubernetes.Implementer, approvalsManager approvals.Manager) *Bot {
client := slack.New(token)
bot := &Bot{
slackClient: client,
slackHTTPClient: client,
k8sImplementer: k8sImplementer,
name: name,
approvalsManager: approvalsManager,
approvalsChannel: approvalsChannel,
approvalsRespCh: make(chan *bot.ApprovalResponse), // don't add buffer to make it blocking
}
return bot
}
// Start - start bot
func (b *Bot) Start(ctx context.Context) error {
// setting root context
b.ctx = ctx
users, err := b.slackClient.GetUsers()
if err != nil {
return err
}
b.users = map[string]string{}
for _, user := range users {
switch user.Name {
case b.name:
if user.IsBot {
b.id = user.ID
}
default:
continue
}
}
if b.id == "" {
return errors.New("could not find bot in the list of names, check if the bot is called \"" + b.name + "\" ")
}
b.msgPrefix = strings.ToLower("<@" + b.id + ">")
// processing messages coming from slack RTM client
go b.startInternal()
// processing slack approval responses
go b.processApprovalResponses()
// subscribing for approval requests
go b.subscribeForApprovals()
return nil
}
func (b *Bot) startInternal() error {
b.slackRTM = b.slackClient.NewRTM()
go b.slackRTM.ManageConnection()
for {
select {
case <-b.ctx.Done():
return nil
case msg := <-b.slackRTM.IncomingEvents:
switch ev := msg.Data.(type) {
case *slack.HelloEvent:
// Ignore hello
case *slack.ConnectedEvent:
// fmt.Println("Infos:", ev.Info)
// fmt.Println("Connection counter:", ev.ConnectionCount)
// Replace #general with your Channel ID
// b.slackRTM.SendMessage(b.slackRTM.NewOutgoingMessage("Hello world", "#general"))
case *slack.MessageEvent:
b.handleMessage(ev)
case *slack.PresenceChangeEvent:
// fmt.Printf("Presence Change: %v\n", ev)
// case *slack.LatencyReport:
// fmt.Printf("Current latency: %v\n", ev.Value)
case *slack.RTMError:
fmt.Printf("Error: %s\n", ev.Error())
case *slack.InvalidAuthEvent:
fmt.Printf("Invalid credentials")
return fmt.Errorf("invalid credentials")
default:
// Ignore other events..
// fmt.Printf("Unexpected: %v\n", msg.Data)
}
}
}
}
func (b *Bot) postMessage(title, message, color string, fields []slack.AttachmentField) error {
params := slack.NewPostMessageParameters()
params.Username = b.name
params.Attachments = []slack.Attachment{
slack.Attachment{
Fallback: message,
Color: color,
Fields: fields,
Footer: "https://keel.sh",
Ts: json.Number(strconv.Itoa(int(time.Now().Unix()))),
},
}
_, _, err := b.slackHTTPClient.PostMessage(b.approvalsChannel, "", params)
if err != nil {
log.WithFields(log.Fields{
"error": err,
}).Error("bot.postMessage: failed to send message")
}
return err
}
func (b *Bot) isApproval(event *slack.MessageEvent, eventText string) (resp *bot.ApprovalResponse, ok bool) {
if strings.HasPrefix(strings.ToLower(eventText), bot.ApprovalResponseKeyword) {
return &bot.ApprovalResponse{
User: event.User,
Status: types.ApprovalStatusApproved,
Text: eventText,
}, true
}
if strings.HasPrefix(strings.ToLower(eventText), bot.RejectResponseKeyword) {
return &bot.ApprovalResponse{
User: event.User,
Status: types.ApprovalStatusRejected,
Text: eventText,
}, true
}
return nil, false
}
// TODO(k): cache results in a map or get this info on startup. Although
// if channel was then recreated (unlikely), we would miss results
func (b *Bot) isApprovalsChannel(event *slack.MessageEvent) bool {
for _, ch := range b.slackRTM.GetInfo().Channels {
if ch.ID == event.Channel && ch.Name == b.approvalsChannel {
return true
}
}
return false
}
func (b *Bot) handleMessage(event *slack.MessageEvent) {
if event.BotID != "" || event.User == "" || event.SubType == "bot_message" {
log.WithFields(log.Fields{
"event_bot_ID": event.BotID,
"event_user": event.User,
"event_subtype": event.SubType,
}).Info("handleMessage: ignoring message")
return
}
eventText := strings.Trim(strings.ToLower(event.Text), " \n\r")
if !b.isBotMessage(event, eventText) {
return
}
eventText = b.trimBot(eventText)
// only accepting approvals from approvals channel
if b.isApprovalsChannel(event) {
approval, ok := b.isApproval(event, eventText)
if ok {
b.approvalsRespCh <- approval
return
}
}
// Responses that are just a canned string response
if responseLines, ok := bot.BotEventTextToResponse[eventText]; ok {
response := strings.Join(responseLines, "\n")
b.respond(event, formatAsSnippet(response))
return
}
if b.isCommand(event, eventText) {
b.handleCommand(event, eventText)
return
}
log.WithFields(log.Fields{
"name": b.name,
"bot_id": b.id,
"command": eventText,
"untrimmed": strings.Trim(strings.ToLower(event.Text), " \n\r"),
}).Debug("handleMessage: bot couldn't recognise command")
}
func (b *Bot) isCommand(event *slack.MessageEvent, eventText string) bool {
if bot.StaticBotCommands[eventText] {
return true
}
for _, prefix := range bot.DynamicBotCommandPrefixes {
if strings.HasPrefix(eventText, prefix) {
return true
}
}
return false
}
func (b *Bot) handleCommand(event *slack.MessageEvent, eventText string) {
switch eventText {
case "get deployments":
log.Info("getting deployments")
response := b.deploymentsResponse(Filter{})
b.respond(event, formatAsSnippet(response))
return
case "get approvals":
response := b.approvalsResponse()
b.respond(event, formatAsSnippet(response))
return
}
// handle dynamic commands
if strings.HasPrefix(eventText, bot.RemoveApprovalPrefix) {
b.respond(event, formatAsSnippet(b.removeApprovalHandler(strings.TrimSpace(strings.TrimPrefix(eventText, bot.RemoveApprovalPrefix)))))
return
}
log.Info("command not found")
}
func (b *Bot) respond(event *slack.MessageEvent, response string) {
b.slackRTM.SendMessage(b.slackRTM.NewOutgoingMessage(response, event.Channel))
}
func (b *Bot) isBotMessage(event *slack.MessageEvent, eventText string) bool {
prefixes := []string{
b.msgPrefix,
"keel",
}
for _, p := range prefixes {
if strings.HasPrefix(eventText, p) {
return true
}
}
// Direct message channels always starts with 'D'
return strings.HasPrefix(event.Channel, "D")
}
func (b *Bot) trimBot(msg string) string {
msg = strings.Replace(msg, strings.ToLower(b.msgPrefix), "", 1)
msg = strings.TrimPrefix(msg, b.name)
msg = strings.Trim(msg, " :\n")
return msg
}
func formatAsSnippet(response string) string {
return "```" + response + "```"
}

View File

@ -1,4 +1,4 @@
package bot
package slack
import (
"context"
@ -9,6 +9,7 @@ import (
"github.com/nlopes/slack"
"github.com/keel-hq/keel/approvals"
b "github.com/keel-hq/keel/bot"
"github.com/keel-hq/keel/cache/memory"
"github.com/keel-hq/keel/constants"
"github.com/keel-hq/keel/extension/approval"
@ -209,10 +210,10 @@ func TestProcessApprovalReply(t *testing.T) {
time.Sleep(1 * time.Second)
// approval resp
bot.approvalsRespCh <- &approvalResponse{
bot.approvalsRespCh <- &b.ApprovalResponse{
User: "123",
Status: types.ApprovalStatusApproved,
Text: fmt.Sprintf("%s %s", approvalResponseKeyword, identifier),
Text: fmt.Sprintf("%s %s", bot.ApprovalResponseKeyword, identifier),
}
time.Sleep(1 * time.Second)
@ -284,10 +285,10 @@ func TestProcessRejectedReply(t *testing.T) {
time.Sleep(1 * time.Second)
// approval resp
bot.approvalsRespCh <- &approvalResponse{
bot.approvalsRespCh <- &b.ApprovalResponse{
User: "123",
Status: types.ApprovalStatusRejected,
Text: fmt.Sprintf("%s %s", rejectResponseKeyword, identifier),
Text: fmt.Sprintf("%s %s", bot.RejectResponseKeyword, identifier),
}
time.Sleep(1 * time.Second)

View File

@ -34,6 +34,10 @@ import (
_ "github.com/keel-hq/keel/extension/notification/slack"
_ "github.com/keel-hq/keel/extension/notification/webhook"
// bots
_ "github.com/keel-hq/keel/bot/hipchat"
_ "github.com/keel-hq/keel/bot/slack"
log "github.com/Sirupsen/logrus"
)
@ -58,7 +62,6 @@ const (
const EnvDebug = "DEBUG"
func main() {
ver := version.GetKeelVersion()
inCluster := kingpin.Flag("incluster", "use in cluster configuration (defaults to 'true'), use '--no-incluster' if running outside of the cluster").Default("true").Bool()
@ -155,12 +158,7 @@ func main() {
teardownTriggers := setupTriggers(ctx, providers, secretsGetter, approvalsManager)
teardownBot, err := setupBot(implementer, approvalsManager)
if err != nil {
log.WithFields(log.Fields{
"error": err,
}).Fatal("main: failed to setup slack bot")
}
bot.Run(implementer, approvalsManager)
signalChan := make(chan os.Signal, 1)
cleanupDone := make(chan bool)
@ -183,7 +181,7 @@ func main() {
// teardownProviders()
providers.Stop()
teardownTriggers()
teardownBot()
bot.Stop()
cleanupDone <- true
}
@ -221,43 +219,6 @@ func setupProviders(k8sImplementer kubernetes.Implementer, sender notification.S
return providers
}
func setupBot(k8sImplementer kubernetes.Implementer, approvalsManager approvals.Manager) (teardown func(), err error) {
if os.Getenv(constants.EnvSlackToken) != "" {
botName := "keel"
if os.Getenv(constants.EnvSlackBotName) != "" {
botName = os.Getenv(constants.EnvSlackBotName)
}
token := os.Getenv(constants.EnvSlackToken)
approvalsChannel := "general"
if os.Getenv(constants.EnvSlackApprovalsChannel) != "" {
approvalsChannel = os.Getenv(constants.EnvSlackApprovalsChannel)
}
slackBot := bot.New(botName, token, approvalsChannel, k8sImplementer, approvalsManager)
ctx, cancel := context.WithCancel(context.Background())
err := slackBot.Start(ctx)
if err != nil {
cancel()
return nil, err
}
teardown := func() {
// cancelling context
cancel()
}
return teardown, nil
}
return func() {}, nil
}
// setupTriggers - setting up triggers. New triggers should be added to this function. Each trigger
// should go through all providers (or not if there is a reason) and submit events)
func setupTriggers(ctx context.Context, providers provider.Providers, secretsGetter secrets.Getter, approvalsManager approvals.Manager) (teardown func()) {

View File

@ -19,6 +19,11 @@ const (
EnvHipchatToken = "HIPCHAT_TOKEN"
EnvHipchatBotName = "HIPCHAT_BOT_NAME"
EnvHipchatChannels = "HIPCHAT_CHANNELS"
EnvHipchatApprovalsChannel = "HIPCHAT_APPROVALS_CHANNEL"
EnvHipchatApprovalsUserName = "HIPCHAT_APPROVALS_USER_NAME"
EnvHipchatApprovalsBotName = "HIPCHAT_APPROVALS_BOT_NAME"
EnvHipchatApprovalsPasswort = "HIPCHAT_APPROVALS_PASSWORT"
)
// EnvNotificationLevel - minimum level for notifications, defaults to info

22
glide.lock generated
View File

@ -1,5 +1,5 @@
hash: b4faf989713037ee4eb401a0af5ea985065140cf7ffdcaab025c62969d5803ea
updated: 2017-12-11T21:33:40.88196567Z
hash: 2b3a6924fbd5b637b899b9bd08c66b36690f23b72ffe140eb14a2016f16770ae
updated: 2017-12-20T20:08:27.365624741+01:00
imports:
- name: cloud.google.com/go
version: 050b16d2314d5fc3d4c9a51e4cd5c7468e77f162
@ -18,6 +18,10 @@ imports:
version: 2efee857e7cfd4f3d0138cc3cbb1b4966962b93a
- name: github.com/BurntSushi/toml
version: b26d9c308763d68093482582cea63d69be07a0f0
- name: github.com/daneharrigan/hipchat
version: 835dc879394a24080bf1c01e199c4cda001b6c46
subpackages:
- xmpp
- name: github.com/davecgh/go-spew
version: 5215b55f46b2b919f50a1df0eaa5886afe4e3b3d
subpackages:
@ -76,6 +80,10 @@ imports:
- ptypes/duration
- ptypes/empty
- ptypes/timestamp
- name: github.com/google/go-querystring
version: 53e6ce116135b80d037921a7fdd5138cf32d7a8a
subpackages:
- query
- name: github.com/google/gofuzz
version: 44d81051d367757e1c7c6a5a86423ece9afcf63c
- name: github.com/googleapis/gax-go
@ -120,6 +128,10 @@ imports:
version: d682213848ed68c0a260ca37d6dd5ace8423f5ba
- name: github.com/spf13/pflag
version: 9ff6c6923cfffbcd502984b8e0c80539a94968b7
- name: github.com/tbruyelle/hipchat-go
version: 749fb9e14beb9995f677c101a754393cecb64b0f
subpackages:
- hipchat
- name: github.com/ugorji/go
version: ded73eae5db7e7a0ef6f55aace87a2873c5d2b74
subpackages:
@ -127,7 +139,7 @@ imports:
- name: github.com/urfave/negroni
version: 5dbbc83f748fc3ad38585842b0aedab546d0ea1e
- name: golang.org/x/crypto
version: 94eea52f7b742c7cbe0b03b22f0c4c8631ece122
version: d585fd2cc9195196078f516b69daff6744ef5e84
subpackages:
- ssh/terminal
- name: golang.org/x/net
@ -200,7 +212,7 @@ imports:
- socket
- urlfetch
- name: google.golang.org/genproto
version: 73cb5d0be5af113b42057925bd6c93e3cd9f60fd
version: a8101f21cf983e773d0c1133ebc5424792003214
subpackages:
- googleapis/api/annotations
- googleapis/iam/v1
@ -225,7 +237,7 @@ imports:
- tap
- transport
- name: gopkg.in/alecthomas/kingpin.v2
version: 1087e65c9441605df944fb12c33f0fe7072d18ca
version: 947dcec5ba9c011838740e680966fd7087a71d0d
- name: gopkg.in/inf.v0
version: 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4
- name: gopkg.in/yaml.v2

View File

@ -1,9 +1,5 @@
package: github.com/keel-hq/keel
import:
# - package: cloud.google.com/go
# version: ^0.10.0
# subpackages:
# - pubsub
- package: cloud.google.com/go
version: ^0.11.0
subpackages:
@ -14,7 +10,6 @@ import:
version: ^1.3.1
- package: github.com/Sirupsen/logrus
- package: github.com/docker/distribution
# version: 5db89f0ca68677abc5eefce8f2a0a772c98ba52d
subpackages:
- digest
- reference
@ -42,14 +37,10 @@ import:
version: 07c182904dbd53199946ba614a412c61d3c548f5
subpackages:
- unix
- windows
# - package: google.golang.org/api
# subpackages:
# - option
- windows
- package: github.com/golang/protobuf
version: 0a4f71a498b7c4812f64969510bcb4eca251e33a
- package: google.golang.org/api
# version: 324744a33f1f37e63dd1695cfb3ec9a3e4a1cb05
version: 295e4bb0ade057ae2cfb9876ab0b54635dbfcea4
subpackages:
- iterator
@ -57,7 +48,7 @@ import:
- support
- transport
- package: google.golang.org/grpc
version: v1.5.0
version: v1.5.0
- package: k8s.io/apimachinery
subpackages:
- status
@ -78,3 +69,4 @@ import:
- pkg/proto/hapi/chart
- pkg/proto/hapi/services
- pkg/strvals
- package: github.com/daneharrigan/hipchat

View File

@ -40,6 +40,14 @@ spec:
# value: your-token-here
# - name: HIPCHAT_CHANNELS
# value: keel-bot
# - name: HIPCHAT_APPROVALS_CHANNEL
# value: "111111_keel-approvals@conf.hipchat.com"
# - name: HIPCHAT_APPROVALS_BOT_NAME
# value: "Mr Bor"
# - name: HIPCHAT_APPROVALS_USER_NAME
# value: "111111_2222222"
# - name: HIPCHAT_APPROVALS_PASSWORT
# value: "pass"
name: keel
command: ["/bin/keel"]
ports:

27
vendor/github.com/daneharrigan/hipchat/LICENSE generated vendored Normal file
View File

@ -0,0 +1,27 @@
Copyright (c) 2015, Dane Harrigan
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 [project] 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 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.

43
vendor/github.com/daneharrigan/hipchat/Readme.md generated vendored Normal file
View File

@ -0,0 +1,43 @@
# hipchat
This is a abstraction in golang to Hipchat's implementation of XMPP. It communicates over
TLS and requires zero knowledge of XML or the XMPP protocol.
* Examples [available here][1]
* Documentation [available here][2]
### bot building
Hipchat treats the "bot" resource differently from any other resource connected to their service. When connecting to Hipchat with a resource of "bot", a chat history will not be sent. Any other resource will receive a chat history.
### example/hello.go
```go
package main
import (
"github.com/daneharrigan/hipchat"
)
func main() {
user := "11111_22222"
pass := "secret"
resource := "bot"
roomJid := "11111_room_name@conf.hipchat.com"
fullName := "Some Bot"
client, err := hipchat.NewClient(user, pass, resource)
if err != nil {
fmt.Printf("client error: %s\n", err)
return
}
client.Status("chat")
client.Join(roomJid, fullName)
client.Say(roomJid, fullName, "Hello")
select {}
}
```
[1]: https://github.com/daneharrigan/hipchat/tree/master/example
[2]: http://godoc.org/github.com/daneharrigan/hipchat

View File

@ -0,0 +1,31 @@
package main
import (
"fmt"
"github.com/daneharrigan/hipchat"
)
func main() {
user := "11111_22222"
pass := "secret"
resource := "bot"
client, err := hipchat.NewClient(user, pass, resource)
if err != nil {
fmt.Printf("client error: %s\n", err)
return
}
client.RequestUsers()
select {
case users := <-client.Users():
for _, user := range users {
if user.Id == client.Id {
fmt.Printf("name: %s\n", user.Name)
fmt.Printf("mention: %s\n", user.MentionName)
}
}
}
}

View File

@ -0,0 +1,26 @@
package main
import (
"fmt"
"github.com/daneharrigan/hipchat"
)
func main() {
user := "11111_22222"
pass := "secret"
resource := "bot"
roomJid := "11111_room_name@conf.hipchat.com"
fullName := "Some Bot"
client, err := hipchat.NewClient(user, pass, resource)
if err != nil {
fmt.Printf("client error: %s\n", err)
return
}
client.Status("chat")
client.Join(roomJid, fullName)
client.Say(roomJid, fullName, "Hello")
select {}
}

View File

@ -0,0 +1,40 @@
package main
import (
"fmt"
"strings"
"github.com/daneharrigan/hipchat"
)
func main() {
user := "11111_22222"
pass := "secret"
resource := "bot"
roomJid := "11111_room_name@conf.hipchat.com"
fullName := "Some Bot"
mentionName := "SomeBot"
client, err := hipchat.NewClient(user, pass, resource)
if err != nil {
fmt.Printf("client error: %s\n", err)
return
}
client.Status("chat")
client.Join(roomJid, fullName)
go client.KeepAlive()
go func() {
for {
select {
case message := <-client.Messages():
if strings.HasPrefix(message.Body, "@"+mentionName) {
client.Say(roomJid, fullName, "Hello")
}
}
}
}()
select {}
}

279
vendor/github.com/daneharrigan/hipchat/hipchat.go generated vendored Normal file
View File

@ -0,0 +1,279 @@
package hipchat
import (
"bytes"
"encoding/xml"
"errors"
"time"
"github.com/daneharrigan/hipchat/xmpp"
)
const (
defaultAuthType = "plain" // or "oauth"
defaultConf = "conf.hipchat.com"
defaultDomain = "chat.hipchat.com"
defaultHost = "chat.hipchat.com"
)
// A Client represents the connection between the application to the HipChat
// service.
type Client struct {
AuthType string
Username string
Password string
Resource string
Id string
// private
mentionNames map[string]string
connection *xmpp.Conn
receivedUsers chan []*User
receivedRooms chan []*Room
receivedMessage chan *Message
host string
domain string
conf string
}
// A Message represents a message received from HipChat.
type Message struct {
From string
To string
Body string
MentionName string
}
// A User represents a member of the HipChat service.
type User struct {
Email string
Id string
Name string
MentionName string
}
// A Room represents a room in HipChat the Client can join to communicate with
// other members..
type Room struct {
Id string
LastActive string
Name string
NumParticipants string
Owner string
Privacy string
RoomId string
Topic string
}
// NewClient creates a new Client connection from the user name, password and
// resource passed to it. It uses default host URL and conf URL.
func NewClient(user, pass, resource, authType string) (*Client, error) {
return NewClientWithServerInfo(user, pass, resource, authType, defaultHost, defaultDomain, defaultConf)
}
// NewClientWithServerInfo creates a new Client connection from the user name, password,
// resource, host URL and conf URL passed to it.
func NewClientWithServerInfo(user, pass, resource, authType, host, domain, conf string) (*Client, error) {
connection, err := xmpp.Dial(host)
var b bytes.Buffer
if err := xml.EscapeText(&b, []byte(pass)); err != nil {
return nil, err
}
c := &Client{
AuthType: authType,
Username: user,
Password: b.String(),
Resource: resource,
Id: user + "@" + domain,
// private
connection: connection,
mentionNames: make(map[string]string),
receivedUsers: make(chan []*User),
receivedRooms: make(chan []*Room),
receivedMessage: make(chan *Message),
host: host,
domain: domain,
conf: conf,
}
if err != nil {
return c, err
}
err = c.authenticate()
if err != nil {
return c, err
}
go c.listen()
return c, nil
}
// Messages returns a read-only channel of Message structs. After joining a
// room, messages will be sent on the channel.
func (c *Client) Messages() <-chan *Message {
return c.receivedMessage
}
// Rooms returns a channel of Room slices
func (c *Client) Rooms() <-chan []*Room {
return c.receivedRooms
}
// Users returns a channel of User slices
func (c *Client) Users() <-chan []*User {
return c.receivedUsers
}
// Status sends a string to HipChat to indicate whether the client is available
// to chat, away or idle.
func (c *Client) Status(s string) {
c.connection.Presence(c.Id, s)
}
// Join accepts the room id and the name used to display the client in the
// room.
func (c *Client) Join(roomId, resource string) {
c.connection.MUCPresence(roomId+"/"+resource, c.Id)
}
// Part accepts the room id to part.
func (c *Client) Part(roomId, name string) {
c.connection.MUCPart(roomId + "/" + name)
}
// Say accepts a room id, the name of the client in the room, and the message
// body and sends the message to the HipChat room.
func (c *Client) Say(roomId, name, body string) {
c.connection.MUCSend("groupchat", roomId, c.Id+"/"+name, body)
}
// PrivSay accepts a client id, the name of the client, and the message
// body and sends the private message to the HipChat
// user.
func (c *Client) PrivSay(user, name, body string) {
c.connection.MUCSend("chat", user, c.Id+"/"+name, body)
}
// KeepAlive is meant to run as a goroutine. It sends a single whitespace
// character to HipChat every 60 seconds. This keeps the connection from
// idling after 150 seconds.
func (c *Client) KeepAlive() {
for _ = range time.Tick(60 * time.Second) {
c.connection.KeepAlive()
}
}
// RequestRooms will send an outgoing request to get
// the room information for all rooms
func (c *Client) RequestRooms() {
c.connection.Discover(c.Id, c.conf)
}
// RequestUsers will send an outgoing request to get
// the user information for all users
func (c *Client) RequestUsers() {
c.connection.Roster(c.Id, c.domain)
}
func (c *Client) authenticate() error {
var errStr string
c.connection.Stream(c.Id, c.host)
for {
element, err := c.connection.Next()
if err != nil {
return err
}
switch element.Name.Local + element.Name.Space {
case "stream" + xmpp.NsStream:
features := c.connection.Features()
if features.StartTLS != nil {
c.connection.StartTLS()
} else {
for _, m := range features.Mechanisms {
if m == "PLAIN" && c.AuthType == "plain" {
c.connection.Auth(c.Username, c.Password, c.Resource)
} else if m == "X-HIPCHAT-OAUTH2" && c.AuthType == "oauth" {
c.connection.Oauth(c.Password, c.Resource)
}
}
}
case "proceed" + xmpp.NsTLS:
c.connection.UseTLS(c.host)
c.connection.Stream(c.Id, c.host)
case "iq" + xmpp.NsJabberClient:
for _, attr := range element.Attr {
if attr.Name.Local == "type" && attr.Value == "result" {
return nil // authenticated
}
}
return errors.New("could not authenticate")
// oauth:
case "failure" + xmpp.NsSASL:
errStr = "Unable to authenticate:"
case "invalid-authzid" + xmpp.NsSASL:
errStr += " no identity provided"
case "not-authorized" + xmpp.NsSASL:
errStr += " token not authorized"
return errors.New(errStr)
case "success" + xmpp.NsSASL:
return nil
}
}
return errors.New("unexpectedly ended auth loop")
}
func (c *Client) listen() {
for {
element, err := c.connection.Next()
if err != nil {
return
}
switch element.Name.Local + element.Name.Space {
case "iq" + xmpp.NsJabberClient: // rooms and rosters
query := c.connection.Query()
switch query.XMLName.Space {
case xmpp.NsDisco:
items := make([]*Room, len(query.Items))
for i, item := range query.Items {
items[i] = &Room{Id: item.Jid,
LastActive: item.LastActive,
NumParticipants: item.NumParticipants,
Name: item.Name,
Owner: item.Owner,
Privacy: item.Privacy,
RoomId: item.RoomId,
Topic: item.Topic,
}
}
c.receivedRooms <- items
case xmpp.NsIqRoster:
items := make([]*User, len(query.Items))
for i, item := range query.Items {
items[i] = &User{Email: item.Email,
Id: item.Jid,
Name: item.Name,
MentionName: item.MentionName,
}
}
c.receivedUsers <- items
}
case "message" + xmpp.NsJabberClient:
attr := xmpp.ToMap(element.Attr)
c.receivedMessage <- &Message{
From: attr["from"],
To: attr["to"],
Body: c.connection.Body(),
}
}
}
panic("unreachable")
}

198
vendor/github.com/daneharrigan/hipchat/xmpp/xmpp.go generated vendored Normal file
View File

@ -0,0 +1,198 @@
package xmpp
import (
"crypto/rand"
"crypto/tls"
"encoding/base64"
"encoding/xml"
"errors"
"fmt"
"html"
"io"
"net"
)
const (
NsJabberClient = "jabber:client"
NsStream = "http://etherx.jabber.org/streams"
NsIqAuth = "jabber:iq:auth"
NsIqRoster = "jabber:iq:roster"
NsSASL = "urn:ietf:params:xml:ns:xmpp-sasl"
NsTLS = "urn:ietf:params:xml:ns:xmpp-tls"
NsDisco = "http://jabber.org/protocol/disco#items"
NsMuc = "http://jabber.org/protocol/muc"
xmlStream = "<stream:stream from='%s' to='%s' version='1.0' xml:lang='en' xmlns='%s' xmlns:stream='%s'>"
xmlStartTLS = "<starttls xmlns='%s'/>"
xmlIqSet = "<iq type='set' id='%s'><query xmlns='%s'><username>%s</username><password>%s</password><resource>%s</resource></query></iq>"
xmlIqGet = "<iq from='%s' to='%s' id='%s' type='get'><query xmlns='%s'/></iq>"
xmlOauth = "<auth xmlns='http://hipchat.com' ver='22' mechanism='oauth2'>%s</auth>"
xmlPresence = "<presence from='%s'><show>%s</show></presence>"
xmlMUCPart = "<presence to='%s' type='unavailable'></presence>"
xmlMUCPresence = "<presence id='%s' to='%s' from='%s'><x xmlns='%s'/></presence>"
xmlMUCMessage = "<message from='%s' id='%s' to='%s' type='%s'><body>%s</body></message>"
)
type required struct{}
type features struct {
Auth xml.Name `xml:"auth"`
XMLName xml.Name `xml:"features"`
StartTLS *required `xml:"starttls>required"`
Mechanisms []string `xml:"mechanisms>mechanism"`
}
type item struct {
Email string `xml:"email,attr"`
Jid string `xml:"jid,attr"`
LastActive string `xml:"x>last_active"`
MentionName string `xml:"mention_name,attr"`
Name string `xml:"name,attr"`
NumParticipants string `xml:"x>num_participants"`
Owner string `xml:"x>owner"`
Privacy string `xml:"x>privacy"`
RoomId string `xml:"x>id"`
Topic string `xml:"x>topic"`
}
type query struct {
XMLName xml.Name `xml:"query"`
Items []*item `xml:"item"`
}
type body struct {
Body string `xml:",innerxml"`
}
type Conn struct {
incoming *xml.Decoder
outgoing net.Conn
}
type Message struct {
Jid string
MentionName string
Body string
}
func (c *Conn) Stream(jid, host string) {
fmt.Fprintf(c.outgoing, xmlStream, jid, host, NsJabberClient, NsStream)
}
func (c *Conn) StartTLS() {
fmt.Fprintf(c.outgoing, xmlStartTLS, NsTLS)
}
func (c *Conn) UseTLS(host string) {
c.outgoing = tls.Client(c.outgoing, &tls.Config{ServerName: host})
c.incoming = xml.NewDecoder(c.outgoing)
}
func (c *Conn) Auth(user, pass, resource string) {
fmt.Fprintf(c.outgoing, xmlIqSet, id(), NsIqAuth, user, pass, resource)
}
func (c *Conn) Oauth(token, resource string) {
msg := "\x00" + token + "\x00" + resource
b64 := base64.StdEncoding.EncodeToString([]byte(msg))
fmt.Fprintf(c.outgoing, xmlOauth, b64)
}
func (c *Conn) Features() *features {
var f features
c.incoming.DecodeElement(&f, nil)
return &f
}
func (c *Conn) Next() (xml.StartElement, error) {
for {
var element xml.StartElement
var err error
var t xml.Token
t, err = c.incoming.Token()
if err != nil {
return element, err
}
switch t := t.(type) {
case xml.StartElement:
element = t
if element.Name.Local == "" {
return element, errors.New("invalid xml response")
}
return element, nil
}
}
panic("unreachable")
}
func (c *Conn) Discover(from, to string) {
fmt.Fprintf(c.outgoing, xmlIqGet, from, to, id(), NsDisco)
}
func (c *Conn) Body() string {
b := new(body)
c.incoming.DecodeElement(b, nil)
return b.Body
}
func (c *Conn) Query() *query {
q := new(query)
c.incoming.DecodeElement(q, nil)
return q
}
func (c *Conn) Presence(jid, pres string) {
fmt.Fprintf(c.outgoing, xmlPresence, jid, pres)
}
func (c *Conn) MUCPart(roomId string) {
fmt.Fprintf(c.outgoing, xmlMUCPart, roomId)
}
func (c *Conn) MUCPresence(roomId, jid string) {
fmt.Fprintf(c.outgoing, xmlMUCPresence, id(), roomId, jid, NsMuc)
}
func (c *Conn) MUCSend(mtype, to, from, body string) {
fmt.Fprintf(c.outgoing, xmlMUCMessage, from, id(), to, mtype, html.EscapeString(body))
}
func (c *Conn) Roster(from, to string) {
fmt.Fprintf(c.outgoing, xmlIqGet, from, to, id(), NsIqRoster)
}
func (c *Conn) KeepAlive() {
fmt.Fprintf(c.outgoing, " ")
}
func Dial(host string) (*Conn, error) {
c := new(Conn)
outgoing, err := net.Dial("tcp", host+":5222")
if err != nil {
return c, err
}
c.outgoing = outgoing
c.incoming = xml.NewDecoder(outgoing)
return c, nil
}
func ToMap(attr []xml.Attr) map[string]string {
m := make(map[string]string)
for _, a := range attr {
m[a.Name.Local] = a.Value
}
return m
}
func id() string {
b := make([]byte, 8)
io.ReadFull(rand.Reader, b)
return fmt.Sprintf("%x", b)
}

View File

@ -1,17 +1,17 @@
language: go
sudo: false
go:
- 1.5
- 1.6
- 1.7
- 1.8
install: go get -v ./hipchat
script:
- go get -u github.com/golang/lint/golint
- golint ./...
- test `gofmt -l . | wc -l` = 0
- make
- make all
matrix:
allow_failures:
go: tip
- go: tip

View File

@ -1,9 +1,30 @@
SRC_DIR=./hipchat
TEST?=./hipchat
VETARGS?=-asmdecl -atomic -bool -buildtags -copylocks -methods -nilfunc -printf -rangeloops -shift -structtags -unsafeptr
include checks.mk
all: test testrace vet
default: test checks
default: test
# test runs the unit tests and vets the code
test:
go test -v $(SRC_DIR) $(TESTARGS) -timeout=30s -parallel=4
TF_ACC= go test -v $(TEST) $(TESTARGS) -timeout=30s -parallel=4
# testrace runs the race checker
testrace:
TF_ACC= go test -race $(TEST) $(TESTARGS)
# vet runs the Go source code static analysis tool `vet` to find
# any common errors
vet:
@go tool vet 2>/dev/null ; if [ $$? -eq 3 ]; then \
go get golang.org/x/tools/cmd/vet; \
fi
@echo "go tool vet $(VETARGS) $(TEST) "
@go tool vet $(VETARGS) $(TEST) ; if [ $$? -eq 1 ]; then \
echo ""; \
echo "Vet found suspicious constructs. Please check the reported constructs"; \
echo "and fix them if necessary before submitting the code for review."; \
exit 1; \
fi
.PHONY: default test updatedeps vet

View File

@ -1,18 +0,0 @@
checks:
go test -race $(SRC_DIR)
@$(call checkbin,go tool vet,golang.org/x/tools/cms/vet)
go tool vet $(SRC_DIR)
@$(call checkbin,golint,github.com/golang/lint/golint)
golint -set_exit_status $(SRC_DIR)
@$(call checkbin,errcheck,github.com/kisielk/errcheck)
errcheck -ignore 'Close' -ignoretests $(SRC_DIR)
@$(call checkbin,structcheck,github.com/opennota/check/cmd/structcheck)
structcheck $(SRC_DIR)
@$(call checkbin,varcheck,github.com/opennota/check/cmd/varcheck)
varcheck $(SRC_DIR)
checkbin = $1 2> /dev/null; if [ $$? -eq 127 ]; then\
echo "Retrieving missing tool $1...";\
go get $2; \
fi;

View File

@ -1 +0,0 @@
hipfile

View File

@ -1 +0,0 @@
hiptail

View File

@ -42,7 +42,7 @@ func main() {
}
msg := m.Message
if len(m.Message) > (maxMsgLen - len(moreString)) {
msg = fmt.Sprintf("%s%s", strings.Replace(m.Message[:len(m.Message)], "\n", " - ", -1), moreString)
msg = fmt.Sprintf("%s%s", strings.Replace(m.Message[:maxMsgLen], "\n", " - ", -1), moreString)
}
fmt.Printf("%s [%s]: %s\n", from, m.Date, msg)
}

View File

@ -35,7 +35,7 @@ func main() {
if *action == "" {
if *roomId == "" {
// If no room is given, look up all rooms and all of their webhooks
rooms, resp, err := c.Room.List(&hipchat.RoomsListOptions{})
rooms, resp, err := c.Room.List()
handleRequestError(resp, err)
for _, room := range rooms.Items {

View File

@ -9,7 +9,6 @@ import (
"fmt"
"io"
"io/ioutil"
"math/rand"
"mime"
"net/http"
"net/url"
@ -19,7 +18,6 @@ import (
"reflect"
"strconv"
"strings"
"time"
"github.com/google/go-querystring/query"
)
@ -34,33 +32,17 @@ type HTTPClient interface {
Do(req *http.Request) (res *http.Response, err error)
}
// LimitData contains the latest Rate Limit or Flood Control data sent with every API call response.
//
// Limit is the number of API calls per period of time
// Remaining is the current number of API calls that can be done before the ResetTime
// ResetTime is the UTC time in Unix epoch format for when the full Limit of API calls will be restored.
type LimitData struct {
Limit int
Remaining int
ResetTime int
}
// Client manages the communication with the HipChat API.
//
// LatestFloodControl contains the response from the latest API call's response headers X-Floodcontrol-{Limit, Remaining, ResetTime}
// LatestRateLimit contains the response from the latest API call's response headers X-Ratelimit-{Limit, Remaining, ResetTime}
// Room gives access to the /room part of the API.
// User gives access to the /user part of the API.
// Emoticon gives access to the /emoticon part of the API.
type Client struct {
authToken string
BaseURL *url.URL
client HTTPClient
LatestFloodControl LimitData
LatestRateLimit LimitData
Room *RoomService
User *UserService
Emoticon *EmoticonService
authToken string
BaseURL *url.URL
client HTTPClient
// Room gives access to the /room part of the API.
Room *RoomService
// User gives access to the /user part of the API.
User *UserService
// Emoticon gives access to the /emoticon part of the API.
Emoticon *EmoticonService
}
// Links represents the HipChat default links.
@ -81,41 +63,23 @@ type ID struct {
ID string `json:"id"`
}
// ListOptions specifies the optional parameters to various List methods that
// ListOptions specifies the optional parameters to various List methods that
// support pagination.
//
// For paginated results, StartIndex represents the first page to display.
// For paginated results, MaxResults reprensents the number of items per page. Default value is 100. Maximum value is 1000.
type ListOptions struct {
// For paginated results, represents the first page to display.
StartIndex int `url:"start-index,omitempty"`
// For paginated results, reprensents the number of items per page.
MaxResults int `url:"max-results,omitempty"`
}
// ExpandOptions specifies which Hipchat collections to automatically expand.
// This functionality is primarily used to reduce the total time to receive the data.
// It also reduces the sheer number of API calls from 1+N, to 1.
//
// cf: https://developer.atlassian.com/hipchat/guide/hipchat-rest-api/api-title-expansion
type ExpandOptions struct {
Expand string `url:"expand,omitempty"`
}
// Color is set of hard-coded string values for the HipChat API for notifications.
// cf: https://www.hipchat.com/docs/apiv2/method/send_room_notification
type Color string
const (
// ColorYellow is the color yellow
ColorYellow Color = "yellow"
// ColorGreen is the color green
ColorGreen Color = "green"
// ColorRed is the color red
ColorRed Color = "red"
// ColorPurple is the color purple
ColorGreen Color = "green"
ColorRed Color = "red"
ColorPurple Color = "purple"
// ColorGray is the color gray
ColorGray Color = "gray"
// ColorRandom is the random "surprise me!" color
ColorGray Color = "gray"
ColorRandom Color = "random"
)
@ -128,46 +92,6 @@ var AuthTest = false
// API calls if AuthTest=true.
var AuthTestResponse = map[string]interface{}{}
// RetryOnRateLimit can be set to true to automatically retry the API call until it succeeds,
// subject to the RateLimitRetryPolicy settings. This behavior is only active when the API
// call returns 429 (StatusTooManyRequests).
var RetryOnRateLimit = false
// RetryPolicy defines a RetryPolicy.
//
// MaxRetries is the maximum number of attempts to make before returning an error
// MinDelay is the initial delay between attempts. This value is multiplied by the current attempt number.
// MaxDelay is the largest delay between attempts.
// JitterDelay is the amount of random jitter to add to the delay.
// JitterBias is the amount of jitter to remove from the delay.
//
// The use of Jitter avoids inadvertant and undesirable synchronization of network
// operations between otherwise unrelated clients.
// cf: https://brooker.co.za/blog/2015/03/21/backoff.html and https://www.awsarchitectureblog.com/2015/03/backoff.html
//
// Using the values of JitterDelay = 250 milliseconds and a JitterBias of negative 125 milliseconds,
// would result in a uniformly distributed Jitter between -125 and +125 milliseconds, centered
// around the current trial Delay (between MinDelay and MaxDelay).
//
//
type RetryPolicy struct {
MaxRetries int
MinDelay time.Duration
MaxDelay time.Duration
JitterDelay time.Duration
JitterBias time.Duration
}
// NoRateLimitRetryPolicy defines the "never retry an API call" policy's values.
var NoRateLimitRetryPolicy = RetryPolicy{0, 1 * time.Second, 1 * time.Second, 500 * time.Millisecond, 0 * time.Millisecond}
// DefaultRateLimitRetryPolicy defines the "up to 300 times, 1 second apart, randomly adding an additional up-to-500 milliseconds of delay" policy.
var DefaultRateLimitRetryPolicy = RetryPolicy{300, 1 * time.Second, 1 * time.Second, 500 * time.Millisecond, 0 * time.Millisecond}
// RateLimitRetryPolicy can be set to a custom RetryPolicy's values,
// or to one of the two predefined ones: NoRateLimitRetryPolicy or DefaultRateLimitRetryPolicy
var RateLimitRetryPolicy = DefaultRateLimitRetryPolicy
// NewClient returns a new HipChat API client. You must provide a valid
// AuthToken retrieved from your HipChat account.
func NewClient(authToken string) *Client {
@ -296,10 +220,7 @@ func (c *Client) NewFileUploadRequest(method, urlStr string, v interface{}) (*ht
"--hipfileboundary\n"
b := &bytes.Buffer{}
_, err = b.Write([]byte(body))
if err != nil {
return nil, err
}
b.Write([]byte(body))
req, err := http.NewRequest(method, u.String(), b)
if err != nil {
@ -314,15 +235,10 @@ func (c *Client) NewFileUploadRequest(method, urlStr string, v interface{}) (*ht
// Do performs the request, the json received in the response is decoded
// and stored in the value pointed by v.
// Do can be used to perform the request created with NewRequest, which
// should be used only for API requests not implemented in this library.
// Do can be used to perform the request created with NewRequest, as the latter
// it should be used only for API requests not implemented in this library.
func (c *Client) Do(req *http.Request, v interface{}) (*http.Response, error) {
var policy = NoRateLimitRetryPolicy
if RetryOnRateLimit {
policy = RateLimitRetryPolicy
}
resp, err := c.doWithRetryPolicy(req, policy)
resp, err := c.client.Do(req)
if err != nil {
return nil, err
}
@ -339,7 +255,7 @@ func (c *Client) Do(req *http.Request, v interface{}) (*http.Response, error) {
if v != nil {
defer resp.Body.Close()
if w, ok := v.(io.Writer); ok {
_, err = io.Copy(w, resp.Body)
io.Copy(w, resp.Body)
} else {
err = json.NewDecoder(resp.Body).Decode(v)
}
@ -348,66 +264,6 @@ func (c *Client) Do(req *http.Request, v interface{}) (*http.Response, error) {
return resp, err
}
func (c *Client) doWithRetryPolicy(req *http.Request, policy RetryPolicy) (*http.Response, error) {
currentTry := 0
for willContinue(currentTry, policy) {
currentTry = currentTry + 1
resp, err := c.client.Do(req)
if err != nil {
return nil, err
}
c.captureRateLimits(resp)
if http.StatusTooManyRequests == resp.StatusCode {
resp.Body.Close()
if willContinue(currentTry, policy) {
sleep(currentTry, policy)
}
} else {
return resp, nil
}
}
return nil, fmt.Errorf("max retries exceeded (%d)", policy.MaxRetries)
}
func willContinue(currentTry int, policy RetryPolicy) bool {
return currentTry <= policy.MaxRetries
}
func sleep(currentTry int, policy RetryPolicy) {
jitter := time.Duration(rand.Int63n(2*int64(policy.JitterDelay))) - policy.JitterBias
linearDelay := time.Duration(currentTry)*policy.MinDelay + jitter
if linearDelay > policy.MaxDelay {
linearDelay = policy.MaxDelay
}
time.Sleep(time.Duration(linearDelay))
}
func setIfPresent(src string, dest *int) {
if len(src) > 0 {
v, err := strconv.Atoi(src)
if err != nil {
*dest = v
}
}
}
func (c *Client) captureRateLimits(resp *http.Response) {
// BY DESIGN:
// if and only if the HTTP Response headers contain the header are the values updated.
// The Floodcontrol limits are orthogonal to the API limits.
// API Limits are consumed for each and every API call.
// The default value for API limits are 500 (app token) or 100 (user token).
// Flood Control limits are consumed only when a user message, room message, or room notification is sent.
// The default value for Flood Control limits is 30 per minute per user token.
setIfPresent(resp.Header.Get("X-Ratelimit-Limit"), &c.LatestRateLimit.Limit)
setIfPresent(resp.Header.Get("X-Ratelimit-Remaining"), &c.LatestRateLimit.Remaining)
setIfPresent(resp.Header.Get("X-Ratelimit-Reset"), &c.LatestRateLimit.ResetTime)
setIfPresent(resp.Header.Get("X-Floodcontrol-Limit"), &c.LatestFloodControl.Limit)
setIfPresent(resp.Header.Get("X-Floodcontrol-Remaining"), &c.LatestFloodControl.Remaining)
setIfPresent(resp.Header.Get("X-Floodcontrol-Reset"), &c.LatestFloodControl.ResetTime)
}
// addOptions adds the parameters in opt as URL query parameters to s. opt
// must be a struct whose fields may contain "url" tags.
func addOptions(s string, opt interface{}) (*url.URL, error) {

View File

@ -72,9 +72,9 @@ func (c *Client) GenerateToken(credentials ClientCredentials, scopes []string) (
content, err := ioutil.ReadAll(resp.Body)
var token OAuthAccessToken
err = json.Unmarshal(content, &token)
json.Unmarshal(content, &token)
return &token, resp, err
return &token, resp, nil
}
const (

View File

@ -25,7 +25,7 @@ type Room struct {
ID int `json:"id"`
Links RoomLinks `json:"links"`
Name string `json:"name"`
XMPPJid string `json:"xmpp_jid"`
XmppJid string `json:"xmpp_jid"`
Statistics RoomStatistics `json:"statistics"`
Created string `json:"created"`
IsArchived bool `json:"is_archived"`
@ -93,7 +93,7 @@ type Card struct {
Format string `json:"format,omitempty"`
URL string `json:"url,omitempty"`
Title string `json:"title"`
Thumbnail *Thumbnail `json:"thumbnail,omitempty"`
Thumbnail *Icon `json:"thumbnail,omitempty"`
Activity *Activity `json:"activity,omitempty"`
Attributes []Attribute `json:"attributes,omitempty"`
ID string `json:"id,omitempty"`
@ -182,7 +182,7 @@ type Thumbnail struct {
URL string `json:"url"`
URL2x string `json:"url@2x,omitempty"`
Width uint `json:"width,omitempty"`
Height uint `json:"height,omitempty"`
Height uint `json:"url,omitempty"`
}
// Attribute represents an attribute on a Card
@ -243,17 +243,12 @@ type InviteRequest struct {
Reason string `json:"reason"`
}
// AddMemberRequest represents a HipChat add member request
type AddMemberRequest struct {
Roles []string `json:"roles,omitempty"`
}
// GlanceRequest represents a HipChat room ui glance
type GlanceRequest struct {
Key string `json:"key"`
Name GlanceName `json:"name"`
Target string `json:"target"`
QueryURL string `json:"queryUrl,omitempty"`
QueryURL string `json:"queryUrl"`
Icon Icon `json:"icon"`
Conditions []*GlanceCondition `json:"conditions,omitempty"`
}
@ -284,7 +279,7 @@ type GlanceUpdate struct {
// GlanceContent is a component of a Glance
type GlanceContent struct {
Status *GlanceStatus `json:"status,omitempty"`
Status GlanceStatus `json:"status"`
Metadata interface{} `json:"metadata,omitempty"`
Label AttributeValue `json:"label"` // AttributeValue{Type, Label}
}
@ -365,7 +360,6 @@ func (c *Card) AddAttribute(mainLabel, subLabel, url, iconURL string) {
// method.
type RoomsListOptions struct {
ListOptions
ExpandOptions
// Include private rooms in the result, API defaults to true
IncludePrivate bool `url:"include-private,omitempty"`
@ -505,7 +499,6 @@ func (r *RoomService) Update(id string, roomReq *UpdateRoomRequest) (*http.Respo
// HistoryOptions represents a HipChat room chat history request.
type HistoryOptions struct {
ListOptions
ExpandOptions
// Either the latest date to fetch history for in ISO-8601 format, or 'recent' to fetch
// the latest 75 messages. Paging isn't supported for 'recent', however they are real-time
@ -518,14 +511,6 @@ type HistoryOptions struct {
// Reverse the output such that the oldest message is first.
// For consistent paging, set to 'false'.
Reverse bool `url:"reverse,omitempty"`
// Either the earliest date to fetch history for the ISO-8601 format string,
// or leave blank to disable this filter.
// to be effective, the API call requires Date also be filled in with an ISO-8601 format string.
EndDate string `url:"end-date,omitempty"`
// Include records about deleted messages into results (body of a message isn't returned). Set to 'true'.
IncludeDeleted bool `url:"include_deleted,omitempty"`
}
// History fetches a room's chat history.
@ -633,27 +618,3 @@ func (r *RoomService) UpdateGlance(id string, glanceUpdateReq *GlanceUpdateReque
return r.client.Do(req, nil)
}
// AddMember adds a member to a private room and sends member's unavailable presence to all room members asynchronously.
//
// HipChat API docs: https://www.hipchat.com/docs/apiv2/method/add_member
func (r *RoomService) AddMember(roomID string, userID string, addMemberReq *AddMemberRequest) (*http.Response, error) {
req, err := r.client.NewRequest("PUT", fmt.Sprintf("room/%s/member/%s", roomID, userID), nil, addMemberReq)
if err != nil {
return nil, err
}
return r.client.Do(req, nil)
}
// RemoveMember removes a member from a private room
//
// HipChat API docs: https://www.hipchat.com/docs/apiv2/method/remove_member
func (r *RoomService) RemoveMember(roomID string, userID string) (*http.Response, error) {
req, err := r.client.NewRequest("DELETE", fmt.Sprintf("room/%s/member/%s", roomID, userID), nil, nil)
if err != nil {
return nil, err
}
return r.client.Do(req, nil)
}

View File

@ -54,7 +54,6 @@ func TestRoomList(t *testing.T) {
testFormValues(t, r, values{
"start-index": "1",
"max-results": "10",
"expand": "expansion",
"include-private": "true",
"include-archived": "true",
})
@ -67,7 +66,7 @@ func TestRoomList(t *testing.T) {
}`)
})
want := &Rooms{Items: []Room{{ID: 1, Name: "n"}}, StartIndex: 1, MaxResults: 1, Links: PageLinks{Links: Links{Self: "s"}}}
opt := &RoomsListOptions{ListOptions{1, 10}, ExpandOptions{"expansion"}, true, true}
opt := &RoomsListOptions{ListOptions{1, 10}, true, true}
rooms, _, err := client.Room.List(opt)
if err != nil {
t.Fatalf("Room.List returns an error %v", err)
@ -126,32 +125,6 @@ func TestRoomNotification(t *testing.T) {
}
}
func TestRoomNotificationCardWithThumbnail(t *testing.T) {
setup()
defer teardown()
thumbnail := &Thumbnail{URL: "http://foo.com", URL2x: "http://foo2x.com", Width: 1, Height: 2}
description := CardDescription{Format: "format", Value: "value"}
card := &Card{Style: "style", Description: description, Title: "title", Thumbnail: thumbnail}
args := &NotificationRequest{Card: card}
mux.HandleFunc("/room/2/notification", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "POST")
v := new(NotificationRequest)
json.NewDecoder(r.Body).Decode(v)
if !reflect.DeepEqual(v, args) {
t.Errorf("Request body %+v, want %+v", v, args)
}
w.WriteHeader(http.StatusNoContent)
})
_, err := client.Room.Notification("2", args)
if err != nil {
t.Fatalf("Room.Notification returns an error %v", err)
}
}
func TestRoomMessage(t *testing.T) {
setup()
defer teardown()
@ -282,14 +255,11 @@ func TestRoomHistory(t *testing.T) {
mux.HandleFunc("/room/1/history", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
testFormValues(t, r, values{
"start-index": "1",
"max-results": "100",
"expand": "expansion",
"date": "date",
"timezone": "tz",
"reverse": "true",
"end-date": "end-date",
"include_deleted": "true",
"start-index": "1",
"max-results": "100",
"date": "date",
"timezone": "tz",
"reverse": "true",
})
fmt.Fprintf(w, `
{
@ -313,7 +283,7 @@ func TestRoomHistory(t *testing.T) {
})
opt := &HistoryOptions{
ListOptions{1, 100}, ExpandOptions{"expansion"}, "date", "tz", true, "end-date", true,
ListOptions{1, 100}, "date", "tz", true,
}
hist, _, err := client.Room.History("1", opt)
if err != nil {
@ -424,7 +394,7 @@ func TestRoomGlanceUpdate(t *testing.T) {
&GlanceUpdate{
Key: "abc",
Content: GlanceContent{
Status: &GlanceStatus{Type: "lozenge", Value: AttributeValue{Type: "default", Label: "something"}},
Status: GlanceStatus{Type: "lozenge", Value: AttributeValue{Type: "default", Label: "something"}},
Label: AttributeValue{Type: "html", Value: "hello"},
},
},
@ -565,7 +535,7 @@ func TestGlanceUpdateRequestJSONEncodeWithString(t *testing.T) {
&GlanceUpdate{
Key: "abc",
Content: GlanceContent{
Status: &GlanceStatus{Type: "lozenge", Value: AttributeValue{Type: "default", Label: "something"}},
Status: GlanceStatus{Type: "lozenge", Value: AttributeValue{Type: "default", Label: "something"}},
Label: AttributeValue{Type: "html", Value: "hello"},
},
},
@ -590,7 +560,7 @@ func TestGlanceContentJSONEncodeWithString(t *testing.T) {
}{
{
GlanceContent{
Status: &GlanceStatus{Type: "lozenge", Value: AttributeValue{Type: "default", Label: "something"}},
Status: GlanceStatus{Type: "lozenge", Value: AttributeValue{Type: "default", Label: "something"}},
Label: AttributeValue{Type: "html", Value: "hello"},
},
`{"status":{"type":"lozenge","value":{"type":"default","label":"something"}},"label":{"type":"html","value":"hello"}}`,
@ -616,7 +586,7 @@ func TestGlanceContentJSONDecodeWithObject(t *testing.T) {
}{
{
GlanceContent{
Status: &GlanceStatus{Type: "lozenge", Value: AttributeValue{Type: "default", Label: "something"}},
Status: GlanceStatus{Type: "lozenge", Value: AttributeValue{Type: "default", Label: "something"}},
Label: AttributeValue{Type: "html", Value: "hello"},
},
`{"status":{"type":"lozenge","value":{"type":"default","label":"something"}},"label":{"type":"html","value":"hello"}}`,
@ -631,8 +601,8 @@ func TestGlanceContentJSONDecodeWithObject(t *testing.T) {
t.Errorf("Decoding of GlanceContent failed: %v", err)
}
if !reflect.DeepEqual(actual.Status, tt.gc.Status) {
t.Fatalf("Unexpected GlanceContent.Status: %+v, want %+v", actual.Status, tt.gc.Status)
if actual.Status != tt.gc.Status {
t.Fatalf("Unexpected GlanceContent.Status: %v", actual.Status)
}
if actual.Label != tt.gc.Label {
@ -647,12 +617,12 @@ func TestGlanceContentJSONDecodeWithObject(t *testing.T) {
func TestGlanceStatusJSONEncodeWithString(t *testing.T) {
gsTests := []struct {
gs *GlanceStatus
gs GlanceStatus
expected string
}{
{&GlanceStatus{Type: "lozenge", Value: AttributeValue{Type: "default", Label: "something"}},
{GlanceStatus{Type: "lozenge", Value: AttributeValue{Type: "default", Label: "something"}},
`{"type":"lozenge","value":{"type":"default","label":"something"}}`},
{&GlanceStatus{Type: "icon", Value: Icon{URL: "z", URL2x: "x"}},
{GlanceStatus{Type: "icon", Value: Icon{URL: "z", URL2x: "x"}},
`{"type":"icon","value":{"url":"z","url@2x":"x"}}`},
}
@ -670,12 +640,12 @@ func TestGlanceStatusJSONEncodeWithString(t *testing.T) {
func TestGlanceStatusJSONDecodeWithObject(t *testing.T) {
gsTests := []struct {
gs *GlanceStatus
gs GlanceStatus
encoded string
}{
{&GlanceStatus{Type: "lozenge", Value: AttributeValue{Type: "default", Label: "something"}},
{GlanceStatus{Type: "lozenge", Value: AttributeValue{Type: "default", Label: "something"}},
`{"type":"lozenge","value":{"type":"default","label":"something"}}`},
{&GlanceStatus{Type: "icon", Value: Icon{URL: "z", URL2x: "x"}},
{GlanceStatus{Type: "icon", Value: Icon{URL: "z", URL2x: "x"}},
`{"type":"icon","value":{"url":"z","url@2x":"x"}}`},
}
@ -696,39 +666,3 @@ func TestGlanceStatusJSONDecodeWithObject(t *testing.T) {
}
}
}
func TestAddMember(t *testing.T) {
setup()
defer teardown()
args := &AddMemberRequest{Roles: []string{"room_member"}}
mux.HandleFunc("/room/1/member/user", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "PUT")
v := new(AddMemberRequest)
json.NewDecoder(r.Body).Decode(v)
if !reflect.DeepEqual(v, args) {
t.Errorf("Request body %+v, want %+v", v, args)
}
})
_, err := client.Room.AddMember("1", "user", args)
if err != nil {
t.Fatalf("Room.AddMember returns an error %v", err)
}
}
func TestRemoveMember(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/room/1/member/user", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "DELETE")
})
_, err := client.Room.RemoveMember("1", "user")
if err != nil {
t.Fatalf("Room.RemoveMember returns an error %v", err)
}
}

View File

@ -50,7 +50,7 @@ type UpdateUserPresenceRequest struct {
// User represents the HipChat user.
type User struct {
XMPPJid string `json:"xmpp_jid"`
XmppJid string `json:"xmpp_jid"`
IsDeleted bool `json:"is_deleted"`
Name string `json:"name"`
LastActive string `json:"last_active"`
@ -121,7 +121,6 @@ func (u *UserService) Message(id string, msgReq *MessageRequest) (*http.Response
// UserListOptions specified the parameters to the UserService.List method.
type UserListOptions struct {
ListOptions
ExpandOptions
// Include active guest users in response.
IncludeGuests bool `url:"include-guests,omitempty"`
// Include deleted users in response.

View File

@ -111,7 +111,7 @@ func TestUserView(t *testing.T) {
"xmpp_jid": "1@chat.hipchat.com"
}`)
})
want := &User{XMPPJid: "1@chat.hipchat.com",
want := &User{XmppJid: "1@chat.hipchat.com",
IsDeleted: false,
Name: "First Last",
LastActive: "1421029691",
@ -145,7 +145,6 @@ func TestUserList(t *testing.T) {
testFormValues(t, r, values{
"start-index": "1",
"max-results": "100",
"expand": "expansion",
"include-guests": "true",
"include-deleted": "true",
})
@ -179,7 +178,6 @@ func TestUserList(t *testing.T) {
opt := &UserListOptions{
ListOptions{StartIndex: 1, MaxResults: 100},
ExpandOptions{"expansion"},
true, true,
}

219
vendor/golang.org/x/crypto/argon2/argon2.go generated vendored Normal file
View File

@ -0,0 +1,219 @@
// Copyright 2017 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 argon2 implements the key derivation function Argon2.
// Argon2 was selected as the winner of the Password Hashing Competition and can
// be used to derive cryptographic keys from passwords.
// Argon2 is specfifed at https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf
package argon2
import (
"encoding/binary"
"sync"
"golang.org/x/crypto/blake2b"
)
// The Argon2 version implemented by this package.
const Version = 0x13
const (
argon2d = iota
argon2i
argon2id
)
// Key derives a key from the password, salt, and cost parameters using Argon2i
// returning a byte slice of length keyLen that can be used as cryptographic key.
// The CPU cost and parallism degree must be greater than zero.
//
// For example, you can get a derived key for e.g. AES-256 (which needs a 32-byte key) by doing:
// `key := argon2.Key([]byte("some password"), salt, 4, 32*1024, 4, 32)`
//
// The recommended parameters for interactive logins as of 2017 are time=4, memory=32*1024.
// The number of threads can be adjusted to the numbers of available CPUs.
// The time parameter specifies the number of passes over the memory and the memory
// parameter specifies the size of the memory in KiB. For example memory=32*1024 sets the
// memory cost to ~32 MB.
// The cost parameters should be increased as memory latency and CPU parallelism increases.
// Remember to get a good random salt.
func Key(password, salt []byte, time, memory uint32, threads uint8, keyLen uint32) []byte {
return deriveKey(argon2i, password, salt, nil, nil, time, memory, threads, keyLen)
}
func deriveKey(mode int, password, salt, secret, data []byte, time, memory uint32, threads uint8, keyLen uint32) []byte {
if time < 1 {
panic("argon2: number of rounds too small")
}
if threads < 1 {
panic("argon2: paralisim degree too low")
}
mem := memory / (4 * uint32(threads)) * (4 * uint32(threads))
if mem < 8*uint32(threads) {
mem = 8 * uint32(threads)
}
B := initBlocks(password, salt, secret, data, time, mem, uint32(threads), keyLen, mode)
processBlocks(B, time, mem, uint32(threads), mode)
return extractKey(B, mem, uint32(threads), keyLen)
}
const blockLength = 128
type block [blockLength]uint64
func initBlocks(password, salt, key, data []byte, time, memory, threads, keyLen uint32, mode int) []block {
var (
block0 [1024]byte
h0 [blake2b.Size + 8]byte
params [24]byte
tmp [4]byte
)
b2, _ := blake2b.New512(nil)
binary.LittleEndian.PutUint32(params[0:4], threads)
binary.LittleEndian.PutUint32(params[4:8], keyLen)
binary.LittleEndian.PutUint32(params[8:12], memory)
binary.LittleEndian.PutUint32(params[12:16], time)
binary.LittleEndian.PutUint32(params[16:20], uint32(Version))
binary.LittleEndian.PutUint32(params[20:24], uint32(mode))
b2.Write(params[:])
binary.LittleEndian.PutUint32(tmp[:], uint32(len(password)))
b2.Write(tmp[:])
b2.Write(password)
binary.LittleEndian.PutUint32(tmp[:], uint32(len(salt)))
b2.Write(tmp[:])
b2.Write(salt)
binary.LittleEndian.PutUint32(tmp[:], uint32(len(key)))
b2.Write(tmp[:])
b2.Write(key)
binary.LittleEndian.PutUint32(tmp[:], uint32(len(data)))
b2.Write(tmp[:])
b2.Write(data)
b2.Sum(h0[:0])
B := make([]block, memory)
for lane := uint32(0); lane < threads; lane++ {
j := lane * (memory / threads)
binary.LittleEndian.PutUint32(h0[blake2b.Size+4:], lane)
binary.LittleEndian.PutUint32(h0[blake2b.Size:], 0)
blake2bHash(block0[:], h0[:])
for i := range B[0] {
B[j+0][i] = binary.LittleEndian.Uint64(block0[i*8:])
}
binary.LittleEndian.PutUint32(h0[blake2b.Size:], 1)
blake2bHash(block0[:], h0[:])
for i := range B[0] {
B[j+1][i] = binary.LittleEndian.Uint64(block0[i*8:])
}
}
return B
}
func processBlocks(B []block, time, memory, threads uint32, mode int) {
const syncPoints = 4
lanes := memory / threads
segments := lanes / syncPoints
processSegment := func(n, slice, lane uint32, wg *sync.WaitGroup) {
var addresses, in, zero block
if mode == argon2i || (mode == argon2id && n == 0 && slice < syncPoints/2) {
in[0] = uint64(n)
in[1] = uint64(lane)
in[2] = uint64(slice)
in[3] = uint64(memory)
in[4] = uint64(time)
in[5] = uint64(mode)
}
index := uint32(0)
if n == 0 && slice == 0 {
index = 2 // we have already generated the first two blocks
if mode == argon2i || (mode == argon2id && n == 0 && slice < syncPoints/2) {
in[6]++
processBlock(&addresses, &in, &zero)
processBlock(&addresses, &addresses, &zero)
}
}
offset := lane*lanes + slice*segments + index
var random uint64
for index < segments {
prev := offset - 1
if index == 0 && slice == 0 {
prev = lane*lanes + lanes - 1 // last block in lane
}
if mode == argon2i || (mode == argon2id && n == 0 && slice < syncPoints/2) {
if index%blockLength == 0 {
in[6]++
processBlock(&addresses, &in, &zero)
processBlock(&addresses, &addresses, &zero)
}
random = addresses[index%blockLength]
} else {
random = B[prev][0]
}
newOffset := indexAlpha(random, lanes, segments, threads, n, slice, lane, index)
processBlockXOR(&B[offset], &B[prev], &B[newOffset])
index, offset = index+1, offset+1
}
wg.Done()
}
for n := uint32(0); n < time; n++ {
for slice := uint32(0); slice < syncPoints; slice++ {
var wg sync.WaitGroup
for lane := uint32(0); lane < threads; lane++ {
wg.Add(1)
go processSegment(n, slice, lane, &wg)
}
wg.Wait()
}
}
}
func extractKey(B []block, memory, threads, keyLen uint32) []byte {
lanes := memory / threads
for lane := uint32(0); lane < threads-1; lane++ {
for i, v := range B[(lane*lanes)+lanes-1] {
B[memory-1][i] ^= v
}
}
var block [1024]byte
for i, v := range B[memory-1] {
binary.LittleEndian.PutUint64(block[i*8:], v)
}
key := make([]byte, keyLen)
blake2bHash(key, block[:])
return key
}
func indexAlpha(rand uint64, lanes, segments, threads, n, slice, lane, index uint32) uint32 {
refLane := uint32(rand>>32) % threads
m, s := 3*segments, (slice+1)%4*segments
if lane == refLane {
m += index
}
if n == 0 {
m, s = slice*segments, 0
if slice == 0 || lane == refLane {
m += index
}
}
if index == 0 || lane == refLane {
m--
}
return phi(rand, uint64(m), uint64(s), refLane, lanes)
}
func phi(rand, m, s uint64, lane, lanes uint32) uint32 {
p := rand & 0xFFFFFFFF
p = (p * p) >> 32
p = (p * m) >> 32
return lane*lanes + uint32((s+m-(p+1))%uint64(lanes))
}

113
vendor/golang.org/x/crypto/argon2/argon2_test.go generated vendored Normal file
View File

@ -0,0 +1,113 @@
// Copyright 2017 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 argon2
import (
"bytes"
"encoding/hex"
"testing"
)
var (
genKatPassword = []byte{
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
}
genKatSalt = []byte{0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02}
genKatSecret = []byte{0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03}
genKatAAD = []byte{0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04}
)
func TestArgon2(t *testing.T) {
defer func(sse4 bool) { useSSE4 = sse4 }(useSSE4)
if useSSE4 {
t.Log("SSE4.1 version")
testArgon2i(t)
testArgon2d(t)
testArgon2id(t)
useSSE4 = false
}
t.Log("generic version")
testArgon2i(t)
testArgon2d(t)
testArgon2id(t)
}
func testArgon2d(t *testing.T) {
want := []byte{
0x51, 0x2b, 0x39, 0x1b, 0x6f, 0x11, 0x62, 0x97,
0x53, 0x71, 0xd3, 0x09, 0x19, 0x73, 0x42, 0x94,
0xf8, 0x68, 0xe3, 0xbe, 0x39, 0x84, 0xf3, 0xc1,
0xa1, 0x3a, 0x4d, 0xb9, 0xfa, 0xbe, 0x4a, 0xcb,
}
hash := deriveKey(argon2d, genKatPassword, genKatSalt, genKatSecret, genKatAAD, 3, 32, 4, 32)
if !bytes.Equal(hash, want) {
t.Errorf("derived key does not match - got: %s , want: %s", hex.EncodeToString(hash), hex.EncodeToString(want))
}
}
func testArgon2i(t *testing.T) {
want := []byte{
0xc8, 0x14, 0xd9, 0xd1, 0xdc, 0x7f, 0x37, 0xaa,
0x13, 0xf0, 0xd7, 0x7f, 0x24, 0x94, 0xbd, 0xa1,
0xc8, 0xde, 0x6b, 0x01, 0x6d, 0xd3, 0x88, 0xd2,
0x99, 0x52, 0xa4, 0xc4, 0x67, 0x2b, 0x6c, 0xe8,
}
hash := deriveKey(argon2i, genKatPassword, genKatSalt, genKatSecret, genKatAAD, 3, 32, 4, 32)
if !bytes.Equal(hash, want) {
t.Errorf("derived key does not match - got: %s , want: %s", hex.EncodeToString(hash), hex.EncodeToString(want))
}
}
func testArgon2id(t *testing.T) {
want := []byte{
0x0d, 0x64, 0x0d, 0xf5, 0x8d, 0x78, 0x76, 0x6c,
0x08, 0xc0, 0x37, 0xa3, 0x4a, 0x8b, 0x53, 0xc9,
0xd0, 0x1e, 0xf0, 0x45, 0x2d, 0x75, 0xb6, 0x5e,
0xb5, 0x25, 0x20, 0xe9, 0x6b, 0x01, 0xe6, 0x59,
}
hash := deriveKey(argon2id, genKatPassword, genKatSalt, genKatSecret, genKatAAD, 3, 32, 4, 32)
if !bytes.Equal(hash, want) {
t.Errorf("derived key does not match - got: %s , want: %s", hex.EncodeToString(hash), hex.EncodeToString(want))
}
}
func benchmarkArgon2(mode int, time, memory uint32, threads uint8, keyLen uint32, b *testing.B) {
password := []byte("password")
salt := []byte("choosing random salts is hard")
b.ReportAllocs()
for i := 0; i < b.N; i++ {
deriveKey(mode, password, salt, nil, nil, time, memory, threads, keyLen)
}
}
func BenchmarkArgon2i(b *testing.B) {
b.Run(" Time: 3 Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2i, 3, 32*1024, 1, 32, b) })
b.Run(" Time: 4 Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2i, 4, 32*1024, 1, 32, b) })
b.Run(" Time: 5 Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2i, 5, 32*1024, 1, 32, b) })
b.Run(" Time: 3 Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2i, 3, 64*1024, 4, 32, b) })
b.Run(" Time: 4 Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2i, 4, 64*1024, 4, 32, b) })
b.Run(" Time: 5 Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2i, 5, 64*1024, 4, 32, b) })
}
func BenchmarkArgon2d(b *testing.B) {
b.Run(" Time: 3, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2d, 3, 32*1024, 1, 32, b) })
b.Run(" Time: 4, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2d, 4, 32*1024, 1, 32, b) })
b.Run(" Time: 5, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2d, 5, 32*1024, 1, 32, b) })
b.Run(" Time: 3, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2d, 3, 64*1024, 4, 32, b) })
b.Run(" Time: 4, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2d, 4, 64*1024, 4, 32, b) })
b.Run(" Time: 5, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2d, 5, 64*1024, 4, 32, b) })
}
func BenchmarkArgon2id(b *testing.B) {
b.Run(" Time: 3, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2id, 3, 32*1024, 1, 32, b) })
b.Run(" Time: 4, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2id, 4, 32*1024, 1, 32, b) })
b.Run(" Time: 5, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2id, 5, 32*1024, 1, 32, b) })
b.Run(" Time: 3, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2id, 3, 64*1024, 4, 32, b) })
b.Run(" Time: 4, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2id, 4, 64*1024, 4, 32, b) })
b.Run(" Time: 5, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2id, 5, 64*1024, 4, 32, b) })
}

53
vendor/golang.org/x/crypto/argon2/blake2b.go generated vendored Normal file
View File

@ -0,0 +1,53 @@
// Copyright 2017 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 argon2
import (
"encoding/binary"
"hash"
"golang.org/x/crypto/blake2b"
)
// blake2bHash computes an arbitrary long hash value of in
// and writes the hash to out.
func blake2bHash(out []byte, in []byte) {
var b2 hash.Hash
if n := len(out); n < blake2b.Size {
b2, _ = blake2b.New(n, nil)
} else {
b2, _ = blake2b.New512(nil)
}
var buffer [blake2b.Size]byte
binary.LittleEndian.PutUint32(buffer[:4], uint32(len(out)))
b2.Write(buffer[:4])
b2.Write(in)
if len(out) <= blake2b.Size {
b2.Sum(out[:0])
return
}
outLen := len(out)
b2.Sum(buffer[:0])
b2.Reset()
copy(out, buffer[:32])
out = out[32:]
for len(out) > blake2b.Size {
b2.Write(buffer[:])
b2.Sum(buffer[:0])
copy(out, buffer[:32])
out = out[32:]
b2.Reset()
}
if outLen%blake2b.Size > 0 { // outLen > 64
r := ((outLen + 31) / 32) - 2 // ⌈τ /32⌉-2
b2, _ = blake2b.New(outLen-32*r, nil)
}
b2.Write(buffer[:])
b2.Sum(out[:0])
}

59
vendor/golang.org/x/crypto/argon2/blamka_amd64.go generated vendored Normal file
View File

@ -0,0 +1,59 @@
// Copyright 2017 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 argon2
func init() {
useSSE4 = supportsSSE4()
}
//go:noescape
func supportsSSE4() bool
//go:noescape
func mixBlocksSSE2(out, a, b, c *block)
//go:noescape
func xorBlocksSSE2(out, a, b, c *block)
//go:noescape
func blamkaSSE4(b *block)
func processBlockSSE(out, in1, in2 *block, xor bool) {
var t block
mixBlocksSSE2(&t, in1, in2, &t)
if useSSE4 {
blamkaSSE4(&t)
} else {
for i := 0; i < blockLength; i += 16 {
blamkaGeneric(
&t[i+0], &t[i+1], &t[i+2], &t[i+3],
&t[i+4], &t[i+5], &t[i+6], &t[i+7],
&t[i+8], &t[i+9], &t[i+10], &t[i+11],
&t[i+12], &t[i+13], &t[i+14], &t[i+15],
)
}
for i := 0; i < blockLength/8; i += 2 {
blamkaGeneric(
&t[i], &t[i+1], &t[16+i], &t[16+i+1],
&t[32+i], &t[32+i+1], &t[48+i], &t[48+i+1],
&t[64+i], &t[64+i+1], &t[80+i], &t[80+i+1],
&t[96+i], &t[96+i+1], &t[112+i], &t[112+i+1],
)
}
}
if xor {
xorBlocksSSE2(out, in1, in2, &t)
} else {
mixBlocksSSE2(out, in1, in2, &t)
}
}
func processBlock(out, in1, in2 *block) {
processBlockSSE(out, in1, in2, false)
}
func processBlockXOR(out, in1, in2 *block) {
processBlockSSE(out, in1, in2, true)
}

252
vendor/golang.org/x/crypto/argon2/blamka_amd64.s generated vendored Normal file
View File

@ -0,0 +1,252 @@
// Copyright 2017 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.
// +build amd64,!gccgo,!appengine
#include "textflag.h"
DATA ·c40<>+0x00(SB)/8, $0x0201000706050403
DATA ·c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b
GLOBL ·c40<>(SB), (NOPTR+RODATA), $16
DATA ·c48<>+0x00(SB)/8, $0x0100070605040302
DATA ·c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a
GLOBL ·c48<>(SB), (NOPTR+RODATA), $16
#define SHUFFLE(v2, v3, v4, v5, v6, v7, t1, t2) \
MOVO v4, t1; \
MOVO v5, v4; \
MOVO t1, v5; \
MOVO v6, t1; \
PUNPCKLQDQ v6, t2; \
PUNPCKHQDQ v7, v6; \
PUNPCKHQDQ t2, v6; \
PUNPCKLQDQ v7, t2; \
MOVO t1, v7; \
MOVO v2, t1; \
PUNPCKHQDQ t2, v7; \
PUNPCKLQDQ v3, t2; \
PUNPCKHQDQ t2, v2; \
PUNPCKLQDQ t1, t2; \
PUNPCKHQDQ t2, v3
#define SHUFFLE_INV(v2, v3, v4, v5, v6, v7, t1, t2) \
MOVO v4, t1; \
MOVO v5, v4; \
MOVO t1, v5; \
MOVO v2, t1; \
PUNPCKLQDQ v2, t2; \
PUNPCKHQDQ v3, v2; \
PUNPCKHQDQ t2, v2; \
PUNPCKLQDQ v3, t2; \
MOVO t1, v3; \
MOVO v6, t1; \
PUNPCKHQDQ t2, v3; \
PUNPCKLQDQ v7, t2; \
PUNPCKHQDQ t2, v6; \
PUNPCKLQDQ t1, t2; \
PUNPCKHQDQ t2, v7
#define HALF_ROUND(v0, v1, v2, v3, v4, v5, v6, v7, t0, c40, c48) \
MOVO v0, t0; \
PMULULQ v2, t0; \
PADDQ v2, v0; \
PADDQ t0, v0; \
PADDQ t0, v0; \
PXOR v0, v6; \
PSHUFD $0xB1, v6, v6; \
MOVO v4, t0; \
PMULULQ v6, t0; \
PADDQ v6, v4; \
PADDQ t0, v4; \
PADDQ t0, v4; \
PXOR v4, v2; \
PSHUFB c40, v2; \
MOVO v0, t0; \
PMULULQ v2, t0; \
PADDQ v2, v0; \
PADDQ t0, v0; \
PADDQ t0, v0; \
PXOR v0, v6; \
PSHUFB c48, v6; \
MOVO v4, t0; \
PMULULQ v6, t0; \
PADDQ v6, v4; \
PADDQ t0, v4; \
PADDQ t0, v4; \
PXOR v4, v2; \
MOVO v2, t0; \
PADDQ v2, t0; \
PSRLQ $63, v2; \
PXOR t0, v2; \
MOVO v1, t0; \
PMULULQ v3, t0; \
PADDQ v3, v1; \
PADDQ t0, v1; \
PADDQ t0, v1; \
PXOR v1, v7; \
PSHUFD $0xB1, v7, v7; \
MOVO v5, t0; \
PMULULQ v7, t0; \
PADDQ v7, v5; \
PADDQ t0, v5; \
PADDQ t0, v5; \
PXOR v5, v3; \
PSHUFB c40, v3; \
MOVO v1, t0; \
PMULULQ v3, t0; \
PADDQ v3, v1; \
PADDQ t0, v1; \
PADDQ t0, v1; \
PXOR v1, v7; \
PSHUFB c48, v7; \
MOVO v5, t0; \
PMULULQ v7, t0; \
PADDQ v7, v5; \
PADDQ t0, v5; \
PADDQ t0, v5; \
PXOR v5, v3; \
MOVO v3, t0; \
PADDQ v3, t0; \
PSRLQ $63, v3; \
PXOR t0, v3
#define LOAD_MSG_0(block, off) \
MOVOU 8*(off+0)(block), X0; \
MOVOU 8*(off+2)(block), X1; \
MOVOU 8*(off+4)(block), X2; \
MOVOU 8*(off+6)(block), X3; \
MOVOU 8*(off+8)(block), X4; \
MOVOU 8*(off+10)(block), X5; \
MOVOU 8*(off+12)(block), X6; \
MOVOU 8*(off+14)(block), X7
#define STORE_MSG_0(block, off) \
MOVOU X0, 8*(off+0)(block); \
MOVOU X1, 8*(off+2)(block); \
MOVOU X2, 8*(off+4)(block); \
MOVOU X3, 8*(off+6)(block); \
MOVOU X4, 8*(off+8)(block); \
MOVOU X5, 8*(off+10)(block); \
MOVOU X6, 8*(off+12)(block); \
MOVOU X7, 8*(off+14)(block)
#define LOAD_MSG_1(block, off) \
MOVOU 8*off+0*8(block), X0; \
MOVOU 8*off+16*8(block), X1; \
MOVOU 8*off+32*8(block), X2; \
MOVOU 8*off+48*8(block), X3; \
MOVOU 8*off+64*8(block), X4; \
MOVOU 8*off+80*8(block), X5; \
MOVOU 8*off+96*8(block), X6; \
MOVOU 8*off+112*8(block), X7
#define STORE_MSG_1(block, off) \
MOVOU X0, 8*off+0*8(block); \
MOVOU X1, 8*off+16*8(block); \
MOVOU X2, 8*off+32*8(block); \
MOVOU X3, 8*off+48*8(block); \
MOVOU X4, 8*off+64*8(block); \
MOVOU X5, 8*off+80*8(block); \
MOVOU X6, 8*off+96*8(block); \
MOVOU X7, 8*off+112*8(block)
#define BLAMKA_ROUND_0(block, off, t0, t1, c40, c48) \
LOAD_MSG_0(block, off); \
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48); \
SHUFFLE(X2, X3, X4, X5, X6, X7, t0, t1); \
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48); \
SHUFFLE_INV(X2, X3, X4, X5, X6, X7, t0, t1); \
STORE_MSG_0(block, off)
#define BLAMKA_ROUND_1(block, off, t0, t1, c40, c48) \
LOAD_MSG_1(block, off); \
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48); \
SHUFFLE(X2, X3, X4, X5, X6, X7, t0, t1); \
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48); \
SHUFFLE_INV(X2, X3, X4, X5, X6, X7, t0, t1); \
STORE_MSG_1(block, off)
// func blamkaSSE4(b *block)
TEXT ·blamkaSSE4(SB), 4, $0-8
MOVQ b+0(FP), AX
MOVOU ·c40<>(SB), X10
MOVOU ·c48<>(SB), X11
BLAMKA_ROUND_0(AX, 0, X8, X9, X10, X11)
BLAMKA_ROUND_0(AX, 16, X8, X9, X10, X11)
BLAMKA_ROUND_0(AX, 32, X8, X9, X10, X11)
BLAMKA_ROUND_0(AX, 48, X8, X9, X10, X11)
BLAMKA_ROUND_0(AX, 64, X8, X9, X10, X11)
BLAMKA_ROUND_0(AX, 80, X8, X9, X10, X11)
BLAMKA_ROUND_0(AX, 96, X8, X9, X10, X11)
BLAMKA_ROUND_0(AX, 112, X8, X9, X10, X11)
BLAMKA_ROUND_1(AX, 0, X8, X9, X10, X11)
BLAMKA_ROUND_1(AX, 2, X8, X9, X10, X11)
BLAMKA_ROUND_1(AX, 4, X8, X9, X10, X11)
BLAMKA_ROUND_1(AX, 6, X8, X9, X10, X11)
BLAMKA_ROUND_1(AX, 8, X8, X9, X10, X11)
BLAMKA_ROUND_1(AX, 10, X8, X9, X10, X11)
BLAMKA_ROUND_1(AX, 12, X8, X9, X10, X11)
BLAMKA_ROUND_1(AX, 14, X8, X9, X10, X11)
RET
// func mixBlocksSSE2(out, a, b, c *block)
TEXT ·mixBlocksSSE2(SB), 4, $0-32
MOVQ out+0(FP), DX
MOVQ a+8(FP), AX
MOVQ b+16(FP), BX
MOVQ a+24(FP), CX
MOVQ $128, BP
loop:
MOVOU 0(AX), X0
MOVOU 0(BX), X1
MOVOU 0(CX), X2
PXOR X1, X0
PXOR X2, X0
MOVOU X0, 0(DX)
ADDQ $16, AX
ADDQ $16, BX
ADDQ $16, CX
ADDQ $16, DX
SUBQ $2, BP
JA loop
RET
// func xorBlocksSSE2(out, a, b, c *block)
TEXT ·xorBlocksSSE2(SB), 4, $0-32
MOVQ out+0(FP), DX
MOVQ a+8(FP), AX
MOVQ b+16(FP), BX
MOVQ a+24(FP), CX
MOVQ $128, BP
loop:
MOVOU 0(AX), X0
MOVOU 0(BX), X1
MOVOU 0(CX), X2
MOVOU 0(DX), X3
PXOR X1, X0
PXOR X2, X0
PXOR X3, X0
MOVOU X0, 0(DX)
ADDQ $16, AX
ADDQ $16, BX
ADDQ $16, CX
ADDQ $16, DX
SUBQ $2, BP
JA loop
RET
// func supportsSSE4() bool
TEXT ·supportsSSE4(SB), 4, $0-1
MOVL $1, AX
CPUID
SHRL $19, CX // Bit 19 indicates SSE4 support
ANDL $1, CX // CX != 0 if support SSE4
MOVB CX, ret+0(FP)
RET

163
vendor/golang.org/x/crypto/argon2/blamka_generic.go generated vendored Normal file
View File

@ -0,0 +1,163 @@
// Copyright 2017 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 argon2
var useSSE4 bool
func processBlockGeneric(out, in1, in2 *block, xor bool) {
var t block
for i := range t {
t[i] = in1[i] ^ in2[i]
}
for i := 0; i < blockLength; i += 16 {
blamkaGeneric(
&t[i+0], &t[i+1], &t[i+2], &t[i+3],
&t[i+4], &t[i+5], &t[i+6], &t[i+7],
&t[i+8], &t[i+9], &t[i+10], &t[i+11],
&t[i+12], &t[i+13], &t[i+14], &t[i+15],
)
}
for i := 0; i < blockLength/8; i += 2 {
blamkaGeneric(
&t[i], &t[i+1], &t[16+i], &t[16+i+1],
&t[32+i], &t[32+i+1], &t[48+i], &t[48+i+1],
&t[64+i], &t[64+i+1], &t[80+i], &t[80+i+1],
&t[96+i], &t[96+i+1], &t[112+i], &t[112+i+1],
)
}
if xor {
for i := range t {
out[i] ^= in1[i] ^ in2[i] ^ t[i]
}
} else {
for i := range t {
out[i] = in1[i] ^ in2[i] ^ t[i]
}
}
}
func blamkaGeneric(t00, t01, t02, t03, t04, t05, t06, t07, t08, t09, t10, t11, t12, t13, t14, t15 *uint64) {
v00, v01, v02, v03 := *t00, *t01, *t02, *t03
v04, v05, v06, v07 := *t04, *t05, *t06, *t07
v08, v09, v10, v11 := *t08, *t09, *t10, *t11
v12, v13, v14, v15 := *t12, *t13, *t14, *t15
v00 += v04 + 2*uint64(uint32(v00))*uint64(uint32(v04))
v12 ^= v00
v12 = v12>>32 | v12<<32
v08 += v12 + 2*uint64(uint32(v08))*uint64(uint32(v12))
v04 ^= v08
v04 = v04>>24 | v04<<40
v00 += v04 + 2*uint64(uint32(v00))*uint64(uint32(v04))
v12 ^= v00
v12 = v12>>16 | v12<<48
v08 += v12 + 2*uint64(uint32(v08))*uint64(uint32(v12))
v04 ^= v08
v04 = v04>>63 | v04<<1
v01 += v05 + 2*uint64(uint32(v01))*uint64(uint32(v05))
v13 ^= v01
v13 = v13>>32 | v13<<32
v09 += v13 + 2*uint64(uint32(v09))*uint64(uint32(v13))
v05 ^= v09
v05 = v05>>24 | v05<<40
v01 += v05 + 2*uint64(uint32(v01))*uint64(uint32(v05))
v13 ^= v01
v13 = v13>>16 | v13<<48
v09 += v13 + 2*uint64(uint32(v09))*uint64(uint32(v13))
v05 ^= v09
v05 = v05>>63 | v05<<1
v02 += v06 + 2*uint64(uint32(v02))*uint64(uint32(v06))
v14 ^= v02
v14 = v14>>32 | v14<<32
v10 += v14 + 2*uint64(uint32(v10))*uint64(uint32(v14))
v06 ^= v10
v06 = v06>>24 | v06<<40
v02 += v06 + 2*uint64(uint32(v02))*uint64(uint32(v06))
v14 ^= v02
v14 = v14>>16 | v14<<48
v10 += v14 + 2*uint64(uint32(v10))*uint64(uint32(v14))
v06 ^= v10
v06 = v06>>63 | v06<<1
v03 += v07 + 2*uint64(uint32(v03))*uint64(uint32(v07))
v15 ^= v03
v15 = v15>>32 | v15<<32
v11 += v15 + 2*uint64(uint32(v11))*uint64(uint32(v15))
v07 ^= v11
v07 = v07>>24 | v07<<40
v03 += v07 + 2*uint64(uint32(v03))*uint64(uint32(v07))
v15 ^= v03
v15 = v15>>16 | v15<<48
v11 += v15 + 2*uint64(uint32(v11))*uint64(uint32(v15))
v07 ^= v11
v07 = v07>>63 | v07<<1
v00 += v05 + 2*uint64(uint32(v00))*uint64(uint32(v05))
v15 ^= v00
v15 = v15>>32 | v15<<32
v10 += v15 + 2*uint64(uint32(v10))*uint64(uint32(v15))
v05 ^= v10
v05 = v05>>24 | v05<<40
v00 += v05 + 2*uint64(uint32(v00))*uint64(uint32(v05))
v15 ^= v00
v15 = v15>>16 | v15<<48
v10 += v15 + 2*uint64(uint32(v10))*uint64(uint32(v15))
v05 ^= v10
v05 = v05>>63 | v05<<1
v01 += v06 + 2*uint64(uint32(v01))*uint64(uint32(v06))
v12 ^= v01
v12 = v12>>32 | v12<<32
v11 += v12 + 2*uint64(uint32(v11))*uint64(uint32(v12))
v06 ^= v11
v06 = v06>>24 | v06<<40
v01 += v06 + 2*uint64(uint32(v01))*uint64(uint32(v06))
v12 ^= v01
v12 = v12>>16 | v12<<48
v11 += v12 + 2*uint64(uint32(v11))*uint64(uint32(v12))
v06 ^= v11
v06 = v06>>63 | v06<<1
v02 += v07 + 2*uint64(uint32(v02))*uint64(uint32(v07))
v13 ^= v02
v13 = v13>>32 | v13<<32
v08 += v13 + 2*uint64(uint32(v08))*uint64(uint32(v13))
v07 ^= v08
v07 = v07>>24 | v07<<40
v02 += v07 + 2*uint64(uint32(v02))*uint64(uint32(v07))
v13 ^= v02
v13 = v13>>16 | v13<<48
v08 += v13 + 2*uint64(uint32(v08))*uint64(uint32(v13))
v07 ^= v08
v07 = v07>>63 | v07<<1
v03 += v04 + 2*uint64(uint32(v03))*uint64(uint32(v04))
v14 ^= v03
v14 = v14>>32 | v14<<32
v09 += v14 + 2*uint64(uint32(v09))*uint64(uint32(v14))
v04 ^= v09
v04 = v04>>24 | v04<<40
v03 += v04 + 2*uint64(uint32(v03))*uint64(uint32(v04))
v14 ^= v03
v14 = v14>>16 | v14<<48
v09 += v14 + 2*uint64(uint32(v09))*uint64(uint32(v14))
v04 ^= v09
v04 = v04>>63 | v04<<1
*t00, *t01, *t02, *t03 = v00, v01, v02, v03
*t04, *t05, *t06, *t07 = v04, v05, v06, v07
*t08, *t09, *t10, *t11 = v08, v09, v10, v11
*t12, *t13, *t14, *t15 = v12, v13, v14, v15
}

15
vendor/golang.org/x/crypto/argon2/blamka_ref.go generated vendored Normal file
View File

@ -0,0 +1,15 @@
// Copyright 2017 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.
// +build !amd64 appengine gccgo
package argon2
func processBlock(out, in1, in2 *block) {
processBlockGeneric(out, in1, in2, false)
}
func processBlockXOR(out, in1, in2 *block) {
processBlockGeneric(out, in1, in2, true)
}

View File

@ -39,7 +39,10 @@ var (
useSSE4 bool
)
var errKeySize = errors.New("blake2b: invalid key size")
var (
errKeySize = errors.New("blake2b: invalid key size")
errHashSize = errors.New("blake2b: invalid hash size")
)
var iv = [8]uint64{
0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
@ -83,7 +86,18 @@ func New384(key []byte) (hash.Hash, error) { return newDigest(Size384, key) }
// key turns the hash into a MAC. The key must between zero and 64 bytes long.
func New256(key []byte) (hash.Hash, error) { return newDigest(Size256, key) }
// New returns a new hash.Hash computing the BLAKE2b checksum with a custom length.
// A non-nil key turns the hash into a MAC. The key must between zero and 64 bytes long.
// The hash size can be a value between 1 and 64 but it is highly recommended to use
// values equal or greater than:
// - 32 if BLAKE2b is used as a hash function (The key is zero bytes long).
// - 16 if BLAKE2b is used as a MAC function (The key is at least 16 bytes long).
func New(size int, key []byte) (hash.Hash, error) { return newDigest(size, key) }
func newDigest(hashSize int, key []byte) (*digest, error) {
if hashSize < 1 || hashSize > Size {
return nil, errHashSize
}
if len(key) > Size {
return nil, errKeySize
}

View File

@ -155,3 +155,22 @@ func TestWithHMACSHA1(t *testing.T) {
func TestWithHMACSHA256(t *testing.T) {
testHash(t, sha256.New, "SHA256", sha256TestVectors)
}
var sink uint8
func benchmark(b *testing.B, h func() hash.Hash) {
password := make([]byte, h().Size())
salt := make([]byte, 8)
for i := 0; i < b.N; i++ {
password = Key(password, salt, 4096, len(password), h)
}
sink += password[0]
}
func BenchmarkHMACSHA1(b *testing.B) {
benchmark(b, sha1.New)
}
func BenchmarkHMACSHA256(b *testing.B) {
benchmark(b, sha256.New)
}

View File

@ -6,10 +6,15 @@ package ssh
import (
"bytes"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"net"
"reflect"
"testing"
"time"
"golang.org/x/crypto/ssh/testdata"
)
// Cert generated by ssh-keygen 6.0p1 Debian-4.
@ -220,3 +225,111 @@ func TestHostKeyCert(t *testing.T) {
}
}
}
func TestCertTypes(t *testing.T) {
var testVars = []struct {
name string
keys func() Signer
}{
{
name: CertAlgoECDSA256v01,
keys: func() Signer {
s, _ := ParsePrivateKey(testdata.PEMBytes["ecdsap256"])
return s
},
},
{
name: CertAlgoECDSA384v01,
keys: func() Signer {
s, _ := ParsePrivateKey(testdata.PEMBytes["ecdsap384"])
return s
},
},
{
name: CertAlgoECDSA521v01,
keys: func() Signer {
s, _ := ParsePrivateKey(testdata.PEMBytes["ecdsap521"])
return s
},
},
{
name: CertAlgoED25519v01,
keys: func() Signer {
s, _ := ParsePrivateKey(testdata.PEMBytes["ed25519"])
return s
},
},
{
name: CertAlgoRSAv01,
keys: func() Signer {
s, _ := ParsePrivateKey(testdata.PEMBytes["rsa"])
return s
},
},
{
name: CertAlgoDSAv01,
keys: func() Signer {
s, _ := ParsePrivateKey(testdata.PEMBytes["dsa"])
return s
},
},
}
k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
t.Fatalf("error generating host key: %v", err)
}
signer, err := NewSignerFromKey(k)
if err != nil {
t.Fatalf("error generating signer for ssh listener: %v", err)
}
conf := &ServerConfig{
PublicKeyCallback: func(c ConnMetadata, k PublicKey) (*Permissions, error) {
return new(Permissions), nil
},
}
conf.AddHostKey(signer)
for _, m := range testVars {
t.Run(m.name, func(t *testing.T) {
c1, c2, err := netPipe()
if err != nil {
t.Fatalf("netPipe: %v", err)
}
defer c1.Close()
defer c2.Close()
go NewServerConn(c1, conf)
priv := m.keys()
if err != nil {
t.Fatalf("error generating ssh pubkey: %v", err)
}
cert := &Certificate{
CertType: UserCert,
Key: priv.PublicKey(),
}
cert.SignCert(rand.Reader, priv)
certSigner, err := NewCertSigner(cert, priv)
if err != nil {
t.Fatalf("error generating cert signer: %v", err)
}
config := &ClientConfig{
User: "user",
HostKeyCallback: func(h string, r net.Addr, k PublicKey) error { return nil },
Auth: []AuthMethod{PublicKeys(certSigner)},
}
_, _, _, err = NewClientConn(c2, "", config)
if err != nil {
t.Fatalf("error connecting: %v", err)
}
})
}
}

View File

@ -256,7 +256,7 @@ func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error)
func isAcceptableAlgo(algo string) bool {
switch algo {
case KeyAlgoRSA, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, KeyAlgoED25519,
CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01:
CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01:
return true
}
return false

View File

@ -23,6 +23,27 @@ MHcCAQEEINGWx0zo6fhJ/0EAfrPzVFyFC9s18lBt3cRoEDhS3ARooAoGCCqGSM49
AwEHoUQDQgAEi9Hdw6KvZcWxfg2IDhA7UkpDtzzt6ZqJXSsFdLd+Kx4S3Sx4cVO+
6/ZOXRnPmNAlLUqjShUsUBBngG0u2fqEqA==
-----END EC PRIVATE KEY-----
`),
"ecdsap256": []byte(`-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIAPCE25zK0PQSnsgVcEbM1mbKTASH4pqb5QJajplDwDZoAoGCCqGSM49
AwEHoUQDQgAEWy8TxGcIHRh5XGpO4dFVfDjeNY+VkgubQrf/eyFJZHxAn1SKraXU
qJUjTKj1z622OxYtJ5P7s9CfAEVsTzLCzg==
-----END EC PRIVATE KEY-----
`),
"ecdsap384": []byte(`-----BEGIN EC PRIVATE KEY-----
MIGkAgEBBDBWfSnMuNKq8J9rQLzzEkx3KAoEohSXqhE/4CdjEYtoU2i22HW80DDS
qQhYNHRAduygBwYFK4EEACKhZANiAAQWaDMAd0HUd8ZiXCX7mYDDnC54gwH/nG43
VhCUEYmF7HMZm/B9Yn3GjFk3qYEDEvuF/52+NvUKBKKaLbh32AWxMv0ibcoba4cz
hL9+hWYhUD9XIUlzMWiZ2y6eBE9PdRI=
-----END EC PRIVATE KEY-----
`),
"ecdsap521": []byte(`-----BEGIN EC PRIVATE KEY-----
MIHcAgEBBEIBrkYpQcy8KTVHNiAkjlFZwee90224Bu6wz94R4OBo+Ts0eoAQG7SF
iaygEDMUbx6kTgXTBcKZ0jrWPKakayNZ/kigBwYFK4EEACOhgYkDgYYABADFuvLV
UoaCDGHcw5uNfdRIsvaLKuWSpLsl48eWGZAwdNG432GDVKduO+pceuE+8XzcyJb+
uMv+D2b11Q/LQUcHJwE6fqbm8m3EtDKPsoKs0u/XUJb0JsH4J8lkZzbUTjvGYamn
FFlRjzoB3Oxu8UQgb+MWPedtH9XYBbg9biz4jJLkXQ==
-----END EC PRIVATE KEY-----
`),
"rsa": []byte(`-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQC8A6FGHDiWCSREAXCq6yBfNVr0xCVG2CzvktFNRpue+RXrGs/2

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -52,13 +52,13 @@ func (ClusterOperationStatus_State) EnumDescriptor() ([]byte, []int) {
// The status of the operation.
type ClusterOperationStatus struct {
// [Output-only] A message containing the operation state.
// Output-only. A message containing the operation state.
State ClusterOperationStatus_State `protobuf:"varint,1,opt,name=state,enum=google.cloud.dataproc.v1.ClusterOperationStatus_State" json:"state,omitempty"`
// [Output-only] A message containing the detailed operation state.
// Output-only. A message containing the detailed operation state.
InnerState string `protobuf:"bytes,2,opt,name=inner_state,json=innerState" json:"inner_state,omitempty"`
// [Output-only]A message containing any operation metadata details.
// Output-only.A message containing any operation metadata details.
Details string `protobuf:"bytes,3,opt,name=details" json:"details,omitempty"`
// [Output-only] The time this state was entered.
// Output-only. The time this state was entered.
StateStartTime *google_protobuf3.Timestamp `protobuf:"bytes,4,opt,name=state_start_time,json=stateStartTime" json:"state_start_time,omitempty"`
}
@ -97,18 +97,22 @@ func (m *ClusterOperationStatus) GetStateStartTime() *google_protobuf3.Timestamp
// Metadata describing the operation.
type ClusterOperationMetadata struct {
// [Output-only] Name of the cluster for the operation.
// Output-only. Name of the cluster for the operation.
ClusterName string `protobuf:"bytes,7,opt,name=cluster_name,json=clusterName" json:"cluster_name,omitempty"`
// [Output-only] Cluster UUID for the operation.
// Output-only. Cluster UUID for the operation.
ClusterUuid string `protobuf:"bytes,8,opt,name=cluster_uuid,json=clusterUuid" json:"cluster_uuid,omitempty"`
// [Output-only] Current operation status.
// Output-only. Current operation status.
Status *ClusterOperationStatus `protobuf:"bytes,9,opt,name=status" json:"status,omitempty"`
// [Output-only] The previous operation status.
// Output-only. The previous operation status.
StatusHistory []*ClusterOperationStatus `protobuf:"bytes,10,rep,name=status_history,json=statusHistory" json:"status_history,omitempty"`
// [Output-only] The operation type.
// Output-only. The operation type.
OperationType string `protobuf:"bytes,11,opt,name=operation_type,json=operationType" json:"operation_type,omitempty"`
// [Output-only] Short description of operation.
// Output-only. Short description of operation.
Description string `protobuf:"bytes,12,opt,name=description" json:"description,omitempty"`
// Output-only. Labels associated with the operation
Labels map[string]string `protobuf:"bytes,13,rep,name=labels" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
// Output-only. Errors encountered during operation execution.
Warnings []string `protobuf:"bytes,14,rep,name=warnings" json:"warnings,omitempty"`
}
func (m *ClusterOperationMetadata) Reset() { *m = ClusterOperationMetadata{} }
@ -158,6 +162,20 @@ func (m *ClusterOperationMetadata) GetDescription() string {
return ""
}
func (m *ClusterOperationMetadata) GetLabels() map[string]string {
if m != nil {
return m.Labels
}
return nil
}
func (m *ClusterOperationMetadata) GetWarnings() []string {
if m != nil {
return m.Warnings
}
return nil
}
func init() {
proto.RegisterType((*ClusterOperationStatus)(nil), "google.cloud.dataproc.v1.ClusterOperationStatus")
proto.RegisterType((*ClusterOperationMetadata)(nil), "google.cloud.dataproc.v1.ClusterOperationMetadata")
@ -167,35 +185,40 @@ func init() {
func init() { proto.RegisterFile("google/cloud/dataproc/v1/operations.proto", fileDescriptor2) }
var fileDescriptor2 = []byte{
// 479 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x53, 0x4f, 0x6f, 0xd3, 0x30,
0x14, 0x27, 0xed, 0xb6, 0x6e, 0xce, 0x56, 0x2a, 0x1f, 0x90, 0x55, 0x26, 0x2d, 0x14, 0x21, 0x95,
0x4b, 0xc2, 0x86, 0x84, 0x90, 0xb8, 0xa0, 0xd1, 0x89, 0x21, 0xc0, 0xad, 0xb2, 0x55, 0x93, 0xb8,
0x44, 0x5e, 0x62, 0x82, 0xa5, 0xc4, 0xb6, 0x6c, 0x67, 0x52, 0x3f, 0x0e, 0xdf, 0x87, 0x0f, 0x85,
0x6c, 0x27, 0x55, 0xd9, 0xe8, 0x01, 0x4e, 0xf1, 0x7b, 0xbf, 0x3f, 0x79, 0xbf, 0xe7, 0x04, 0xbc,
0x2c, 0x85, 0x28, 0x2b, 0x9a, 0xe4, 0x95, 0x68, 0x8a, 0xa4, 0x20, 0x86, 0x48, 0x25, 0xf2, 0xe4,
0xee, 0x34, 0x11, 0x92, 0x2a, 0x62, 0x98, 0xe0, 0x3a, 0x96, 0x4a, 0x18, 0x01, 0x91, 0xa7, 0xc6,
0x8e, 0x1a, 0x77, 0xd4, 0xf8, 0xee, 0x74, 0x7c, 0xdc, 0x9a, 0x10, 0xc9, 0x12, 0xc2, 0xb9, 0x30,
0x9b, 0xba, 0xf1, 0xf3, 0x16, 0xad, 0x04, 0x2f, 0x55, 0xc3, 0x39, 0xe3, 0xe5, 0x03, 0xf3, 0xf1,
0xd3, 0x96, 0xe4, 0xaa, 0xdb, 0xe6, 0x7b, 0x42, 0x6b, 0x69, 0x56, 0x2d, 0x78, 0x72, 0x1f, 0x34,
0xac, 0xa6, 0xda, 0x90, 0x5a, 0x7a, 0xc2, 0xe4, 0x67, 0x0f, 0x3c, 0xf9, 0x50, 0x35, 0xda, 0x50,
0x35, 0xef, 0x9c, 0xaf, 0x0c, 0x31, 0x8d, 0x86, 0x5f, 0xc0, 0xae, 0x36, 0xc4, 0x50, 0x14, 0x44,
0xc1, 0x74, 0x78, 0xf6, 0x26, 0xde, 0x96, 0x22, 0xfe, 0xbb, 0x41, 0x6c, 0x1f, 0x34, 0xf5, 0x26,
0xf0, 0x04, 0x84, 0x8c, 0x73, 0xaa, 0x32, 0xef, 0xd9, 0x8b, 0x82, 0xe9, 0x41, 0x0a, 0x5c, 0xcb,
0xf1, 0x20, 0x02, 0x83, 0x82, 0x1a, 0xc2, 0x2a, 0x8d, 0xfa, 0x0e, 0xec, 0x4a, 0x38, 0x03, 0x23,
0x27, 0xb2, 0x52, 0x65, 0x32, 0x1b, 0x01, 0xed, 0x44, 0xc1, 0x34, 0x3c, 0x1b, 0x77, 0x33, 0x75,
0xf9, 0xe2, 0xeb, 0x2e, 0x5f, 0x3a, 0x74, 0x9a, 0x2b, 0x2b, 0xb1, 0xcd, 0xc9, 0x5b, 0xb0, 0xeb,
0x5f, 0x14, 0x82, 0xc1, 0x12, 0x7f, 0xc6, 0xf3, 0x1b, 0x3c, 0x7a, 0x64, 0x8b, 0xc5, 0x05, 0x9e,
0x7d, 0xc2, 0x1f, 0x47, 0x81, 0x2d, 0xd2, 0x25, 0xc6, 0xb6, 0xe8, 0xc1, 0x7d, 0xb0, 0x33, 0x9b,
0xe3, 0x8b, 0x51, 0x7f, 0xf2, 0xab, 0x07, 0xd0, 0xfd, 0x88, 0x5f, 0xa9, 0x21, 0x76, 0x05, 0xf0,
0x19, 0x38, 0xcc, 0x3d, 0x96, 0x71, 0x52, 0x53, 0x34, 0x70, 0xb3, 0x87, 0x6d, 0x0f, 0x93, 0x9a,
0x6e, 0x52, 0x9a, 0x86, 0x15, 0x68, 0xff, 0x0f, 0xca, 0xb2, 0x61, 0x05, 0xbc, 0x04, 0x7b, 0xda,
0x2d, 0x0d, 0x1d, 0xb8, 0x60, 0xaf, 0xfe, 0x75, 0xd9, 0x69, 0xab, 0x87, 0x37, 0x60, 0xe8, 0x4f,
0xd9, 0x0f, 0xa6, 0x8d, 0x50, 0x2b, 0x04, 0xa2, 0xfe, 0x7f, 0x39, 0x1e, 0x79, 0x9f, 0x4b, 0x6f,
0x03, 0x5f, 0x80, 0xe1, 0xfa, 0xdb, 0xcb, 0xcc, 0x4a, 0x52, 0x14, 0xba, 0x1c, 0x47, 0xeb, 0xee,
0xf5, 0x4a, 0x52, 0x18, 0x81, 0xb0, 0xa0, 0x3a, 0x57, 0x4c, 0xda, 0x16, 0x3a, 0xf4, 0x59, 0x37,
0x5a, 0xe7, 0x1a, 0x1c, 0xe7, 0xa2, 0xde, 0x3a, 0xce, 0xf9, 0xe3, 0xf5, 0x20, 0x7a, 0x61, 0xaf,
0x75, 0x11, 0x7c, 0x7b, 0xdf, 0x92, 0x4b, 0x51, 0x11, 0x5e, 0xc6, 0x42, 0x95, 0x49, 0x49, 0xb9,
0xbb, 0xf4, 0xc4, 0x43, 0x44, 0x32, 0xfd, 0xf0, 0x57, 0x7c, 0xd7, 0x9d, 0x6f, 0xf7, 0x1c, 0xf9,
0xf5, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0x2c, 0x8c, 0x74, 0x3e, 0xb6, 0x03, 0x00, 0x00,
// 553 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0x61, 0x6b, 0xd3, 0x40,
0x18, 0x36, 0xcd, 0xb6, 0xb6, 0x97, 0xb5, 0x96, 0x43, 0xe4, 0x88, 0x83, 0xc5, 0x8a, 0x50, 0xbf,
0x24, 0x6e, 0x82, 0x4c, 0x05, 0x91, 0xd9, 0xe2, 0xc4, 0x99, 0x96, 0x6c, 0x75, 0xe0, 0x97, 0x72,
0x6d, 0xce, 0x18, 0x4c, 0xee, 0xc2, 0xdd, 0xa5, 0x92, 0x9f, 0xe3, 0xef, 0xf4, 0x8b, 0xdc, 0x5d,
0x52, 0xea, 0xe6, 0x40, 0xfd, 0xd4, 0x7b, 0xde, 0xf7, 0x79, 0x9e, 0xbe, 0xcf, 0xcb, 0xdb, 0x82,
0x27, 0x09, 0x63, 0x49, 0x46, 0x82, 0x55, 0xc6, 0xca, 0x38, 0x88, 0xb1, 0xc4, 0x05, 0x67, 0xab,
0x60, 0x7d, 0x14, 0xb0, 0x82, 0x70, 0x2c, 0x53, 0x46, 0x85, 0x5f, 0x70, 0x26, 0x19, 0x44, 0x86,
0xea, 0x6b, 0xaa, 0xdf, 0x50, 0xfd, 0xf5, 0x91, 0x7b, 0x50, 0x9b, 0xe0, 0x22, 0x0d, 0x30, 0xa5,
0x4c, 0x6e, 0xeb, 0xdc, 0x47, 0x75, 0x37, 0x63, 0x34, 0xe1, 0x25, 0xa5, 0x29, 0x4d, 0x6e, 0x98,
0xbb, 0x0f, 0x6a, 0x92, 0x46, 0xcb, 0xf2, 0x4b, 0x40, 0xf2, 0x42, 0x56, 0x75, 0xf3, 0xf0, 0x7a,
0x53, 0xa6, 0x39, 0x11, 0x12, 0xe7, 0x85, 0x21, 0x0c, 0x7f, 0xb4, 0xc0, 0xfd, 0xb7, 0x59, 0x29,
0x24, 0xe1, 0xd3, 0xc6, 0xf9, 0x42, 0x62, 0x59, 0x0a, 0x78, 0x0e, 0x76, 0x85, 0xc4, 0x92, 0x20,
0xcb, 0xb3, 0x46, 0xfd, 0xe3, 0xe7, 0xfe, 0x6d, 0x29, 0xfc, 0x3f, 0x1b, 0xf8, 0xea, 0x83, 0x44,
0xc6, 0x04, 0x1e, 0x02, 0x27, 0xa5, 0x94, 0xf0, 0x85, 0xf1, 0x6c, 0x79, 0xd6, 0xa8, 0x1b, 0x01,
0x5d, 0xd2, 0x3c, 0x88, 0x40, 0x3b, 0x26, 0x12, 0xa7, 0x99, 0x40, 0xb6, 0x6e, 0x36, 0x10, 0x8e,
0xc1, 0x40, 0x8b, 0x94, 0x94, 0xcb, 0x85, 0x8a, 0x80, 0x76, 0x3c, 0x6b, 0xe4, 0x1c, 0xbb, 0xcd,
0x4c, 0x4d, 0x3e, 0xff, 0xb2, 0xc9, 0x17, 0xf5, 0xb5, 0xe6, 0x42, 0x49, 0x54, 0x71, 0x78, 0x02,
0x76, 0xcd, 0x17, 0x39, 0xa0, 0x3d, 0x0f, 0x3f, 0x84, 0xd3, 0xab, 0x70, 0x70, 0x47, 0x81, 0xd9,
0x24, 0x1c, 0xbf, 0x0f, 0xdf, 0x0d, 0x2c, 0x05, 0xa2, 0x79, 0x18, 0x2a, 0xd0, 0x82, 0x1d, 0xb0,
0x33, 0x9e, 0x86, 0x93, 0x81, 0x3d, 0xfc, 0x69, 0x03, 0x74, 0x3d, 0xe2, 0x47, 0x22, 0xb1, 0x5a,
0x01, 0x7c, 0x08, 0xf6, 0x57, 0xa6, 0xb7, 0xa0, 0x38, 0x27, 0xa8, 0xad, 0x67, 0x77, 0xea, 0x5a,
0x88, 0x73, 0xb2, 0x4d, 0x29, 0xcb, 0x34, 0x46, 0x9d, 0xdf, 0x28, 0xf3, 0x32, 0x8d, 0xe1, 0x19,
0xd8, 0x13, 0x7a, 0x69, 0xa8, 0xab, 0x83, 0x3d, 0xfd, 0xd7, 0x65, 0x47, 0xb5, 0x1e, 0x5e, 0x81,
0xbe, 0x79, 0x2d, 0xbe, 0xa6, 0x42, 0x32, 0x5e, 0x21, 0xe0, 0xd9, 0xff, 0xe5, 0xd8, 0x33, 0x3e,
0x67, 0xc6, 0x06, 0x3e, 0x06, 0xfd, 0xcd, 0xed, 0x2d, 0x64, 0x55, 0x10, 0xe4, 0xe8, 0x1c, 0xbd,
0x4d, 0xf5, 0xb2, 0x2a, 0x08, 0xf4, 0x80, 0x13, 0x13, 0xb1, 0xe2, 0x69, 0xa1, 0x4a, 0x68, 0xdf,
0x64, 0xdd, 0x2a, 0xc1, 0x4f, 0x60, 0x2f, 0xc3, 0x4b, 0x92, 0x09, 0xd4, 0xd3, 0x93, 0xbd, 0xfe,
0xfb, 0xc9, 0x9a, 0xad, 0xfb, 0xe7, 0xda, 0x60, 0x42, 0x25, 0xaf, 0xa2, 0xda, 0x0d, 0xba, 0xa0,
0xf3, 0x1d, 0x73, 0xf5, 0x23, 0x11, 0xa8, 0xef, 0xd9, 0xa3, 0x6e, 0xb4, 0xc1, 0xee, 0x0b, 0xe0,
0x6c, 0x49, 0xe0, 0x00, 0xd8, 0xdf, 0x48, 0xa5, 0x0f, 0xbb, 0x1b, 0xa9, 0x27, 0xbc, 0x07, 0x76,
0xd7, 0x38, 0x2b, 0x9b, 0xc3, 0x34, 0xe0, 0x65, 0xeb, 0xc4, 0x3a, 0x15, 0xe0, 0x60, 0xc5, 0xf2,
0x5b, 0x67, 0x3c, 0xbd, 0xbb, 0x99, 0x4e, 0xcc, 0xd4, 0x15, 0xce, 0xac, 0xcf, 0x6f, 0x6a, 0x72,
0xc2, 0x32, 0x4c, 0x13, 0x9f, 0xf1, 0x24, 0x48, 0x08, 0xd5, 0x37, 0x1a, 0x98, 0x16, 0x2e, 0x52,
0x71, 0xf3, 0x9f, 0xe3, 0x55, 0xf3, 0x5e, 0xee, 0x69, 0xf2, 0xb3, 0x5f, 0x01, 0x00, 0x00, 0xff,
0xff, 0x09, 0x4c, 0x3d, 0x35, 0x65, 0x04, 0x00, 0x00,
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,221 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: google/cloud/dataproc/v1beta2/operations.proto
package dataproc
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import _ "google.golang.org/genproto/googleapis/api/annotations"
import google_protobuf5 "github.com/golang/protobuf/ptypes/timestamp"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// The operation state.
type ClusterOperationStatus_State int32
const (
// Unused.
ClusterOperationStatus_UNKNOWN ClusterOperationStatus_State = 0
// The operation has been created.
ClusterOperationStatus_PENDING ClusterOperationStatus_State = 1
// The operation is running.
ClusterOperationStatus_RUNNING ClusterOperationStatus_State = 2
// The operation is done; either cancelled or completed.
ClusterOperationStatus_DONE ClusterOperationStatus_State = 3
)
var ClusterOperationStatus_State_name = map[int32]string{
0: "UNKNOWN",
1: "PENDING",
2: "RUNNING",
3: "DONE",
}
var ClusterOperationStatus_State_value = map[string]int32{
"UNKNOWN": 0,
"PENDING": 1,
"RUNNING": 2,
"DONE": 3,
}
func (x ClusterOperationStatus_State) String() string {
return proto.EnumName(ClusterOperationStatus_State_name, int32(x))
}
func (ClusterOperationStatus_State) EnumDescriptor() ([]byte, []int) {
return fileDescriptor2, []int{0, 0}
}
// The status of the operation.
type ClusterOperationStatus struct {
// Output-only. A message containing the operation state.
State ClusterOperationStatus_State `protobuf:"varint,1,opt,name=state,enum=google.cloud.dataproc.v1beta2.ClusterOperationStatus_State" json:"state,omitempty"`
// Output-only. A message containing the detailed operation state.
InnerState string `protobuf:"bytes,2,opt,name=inner_state,json=innerState" json:"inner_state,omitempty"`
// Output-only.A message containing any operation metadata details.
Details string `protobuf:"bytes,3,opt,name=details" json:"details,omitempty"`
// Output-only. The time this state was entered.
StateStartTime *google_protobuf5.Timestamp `protobuf:"bytes,4,opt,name=state_start_time,json=stateStartTime" json:"state_start_time,omitempty"`
}
func (m *ClusterOperationStatus) Reset() { *m = ClusterOperationStatus{} }
func (m *ClusterOperationStatus) String() string { return proto.CompactTextString(m) }
func (*ClusterOperationStatus) ProtoMessage() {}
func (*ClusterOperationStatus) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{0} }
func (m *ClusterOperationStatus) GetState() ClusterOperationStatus_State {
if m != nil {
return m.State
}
return ClusterOperationStatus_UNKNOWN
}
func (m *ClusterOperationStatus) GetInnerState() string {
if m != nil {
return m.InnerState
}
return ""
}
func (m *ClusterOperationStatus) GetDetails() string {
if m != nil {
return m.Details
}
return ""
}
func (m *ClusterOperationStatus) GetStateStartTime() *google_protobuf5.Timestamp {
if m != nil {
return m.StateStartTime
}
return nil
}
// Metadata describing the operation.
type ClusterOperationMetadata struct {
// Output-only. Name of the cluster for the operation.
ClusterName string `protobuf:"bytes,7,opt,name=cluster_name,json=clusterName" json:"cluster_name,omitempty"`
// Output-only. Cluster UUID for the operation.
ClusterUuid string `protobuf:"bytes,8,opt,name=cluster_uuid,json=clusterUuid" json:"cluster_uuid,omitempty"`
// Output-only. Current operation status.
Status *ClusterOperationStatus `protobuf:"bytes,9,opt,name=status" json:"status,omitempty"`
// Output-only. The previous operation status.
StatusHistory []*ClusterOperationStatus `protobuf:"bytes,10,rep,name=status_history,json=statusHistory" json:"status_history,omitempty"`
// Output-only. The operation type.
OperationType string `protobuf:"bytes,11,opt,name=operation_type,json=operationType" json:"operation_type,omitempty"`
// Output-only. Short description of operation.
Description string `protobuf:"bytes,12,opt,name=description" json:"description,omitempty"`
// Output-only. Labels associated with the operation
Labels map[string]string `protobuf:"bytes,13,rep,name=labels" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
// Output-only. Errors encountered during operation execution.
Warnings []string `protobuf:"bytes,14,rep,name=warnings" json:"warnings,omitempty"`
}
func (m *ClusterOperationMetadata) Reset() { *m = ClusterOperationMetadata{} }
func (m *ClusterOperationMetadata) String() string { return proto.CompactTextString(m) }
func (*ClusterOperationMetadata) ProtoMessage() {}
func (*ClusterOperationMetadata) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{1} }
func (m *ClusterOperationMetadata) GetClusterName() string {
if m != nil {
return m.ClusterName
}
return ""
}
func (m *ClusterOperationMetadata) GetClusterUuid() string {
if m != nil {
return m.ClusterUuid
}
return ""
}
func (m *ClusterOperationMetadata) GetStatus() *ClusterOperationStatus {
if m != nil {
return m.Status
}
return nil
}
func (m *ClusterOperationMetadata) GetStatusHistory() []*ClusterOperationStatus {
if m != nil {
return m.StatusHistory
}
return nil
}
func (m *ClusterOperationMetadata) GetOperationType() string {
if m != nil {
return m.OperationType
}
return ""
}
func (m *ClusterOperationMetadata) GetDescription() string {
if m != nil {
return m.Description
}
return ""
}
func (m *ClusterOperationMetadata) GetLabels() map[string]string {
if m != nil {
return m.Labels
}
return nil
}
func (m *ClusterOperationMetadata) GetWarnings() []string {
if m != nil {
return m.Warnings
}
return nil
}
func init() {
proto.RegisterType((*ClusterOperationStatus)(nil), "google.cloud.dataproc.v1beta2.ClusterOperationStatus")
proto.RegisterType((*ClusterOperationMetadata)(nil), "google.cloud.dataproc.v1beta2.ClusterOperationMetadata")
proto.RegisterEnum("google.cloud.dataproc.v1beta2.ClusterOperationStatus_State", ClusterOperationStatus_State_name, ClusterOperationStatus_State_value)
}
func init() { proto.RegisterFile("google/cloud/dataproc/v1beta2/operations.proto", fileDescriptor2) }
var fileDescriptor2 = []byte{
// 537 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0x5f, 0x8b, 0xd3, 0x4e,
0x14, 0xfd, 0xa5, 0xff, 0x7b, 0xb3, 0xed, 0xaf, 0x0c, 0x22, 0x43, 0x51, 0x36, 0x5b, 0x10, 0xfa,
0x94, 0x60, 0x45, 0x58, 0xdd, 0xb7, 0xdd, 0x16, 0x15, 0xdd, 0xb4, 0x66, 0xb7, 0x08, 0x2a, 0x94,
0x69, 0x33, 0xc6, 0x60, 0x3a, 0x13, 0x66, 0x26, 0x2b, 0x7d, 0xf0, 0x0b, 0xf8, 0x41, 0xfc, 0x9c,
0x32, 0x33, 0x49, 0xa9, 0xa2, 0x0b, 0xee, 0x53, 0xe7, 0xde, 0x7b, 0xce, 0x99, 0x73, 0xa6, 0x97,
0x80, 0x9f, 0x70, 0x9e, 0x64, 0x34, 0xd8, 0x64, 0xbc, 0x88, 0x83, 0x98, 0x28, 0x92, 0x0b, 0xbe,
0x09, 0x6e, 0x1e, 0xaf, 0xa9, 0x22, 0x93, 0x80, 0xe7, 0x54, 0x10, 0x95, 0x72, 0x26, 0xfd, 0x5c,
0x70, 0xc5, 0xd1, 0x43, 0x8b, 0xf7, 0x0d, 0xde, 0xaf, 0xf0, 0x7e, 0x89, 0x1f, 0x3e, 0x28, 0xe5,
0x48, 0x9e, 0x06, 0x84, 0x31, 0xae, 0x0e, 0xc9, 0xc3, 0xe3, 0x72, 0x6a, 0xaa, 0x75, 0xf1, 0x29,
0x50, 0xe9, 0x96, 0x4a, 0x45, 0xb6, 0xb9, 0x05, 0x8c, 0x7e, 0xd4, 0xe0, 0xfe, 0x45, 0x56, 0x48,
0x45, 0xc5, 0xbc, 0xba, 0xf9, 0x4a, 0x11, 0x55, 0x48, 0xf4, 0x16, 0x9a, 0x52, 0x11, 0x45, 0xb1,
0xe3, 0x39, 0xe3, 0xfe, 0xe4, 0xcc, 0xbf, 0xd5, 0x88, 0xff, 0x67, 0x15, 0x5f, 0xff, 0xd0, 0xc8,
0x2a, 0xa1, 0x63, 0x70, 0x53, 0xc6, 0xa8, 0x58, 0x59, 0xe1, 0x9a, 0xe7, 0x8c, 0xbb, 0x11, 0x98,
0x96, 0xc1, 0x21, 0x0c, 0xed, 0x98, 0x2a, 0x92, 0x66, 0x12, 0xd7, 0xcd, 0xb0, 0x2a, 0xd1, 0x14,
0x06, 0x86, 0xa4, 0xa9, 0x42, 0xad, 0x74, 0x0e, 0xdc, 0xf0, 0x9c, 0xb1, 0x3b, 0x19, 0x56, 0xc6,
0xaa, 0x90, 0xfe, 0x75, 0x15, 0x32, 0xea, 0x1b, 0xce, 0x95, 0xa6, 0xe8, 0xe6, 0xe8, 0x14, 0x9a,
0xf6, 0x22, 0x17, 0xda, 0xcb, 0xf0, 0x75, 0x38, 0x7f, 0x17, 0x0e, 0xfe, 0xd3, 0xc5, 0x62, 0x16,
0x4e, 0x5f, 0x85, 0x2f, 0x06, 0x8e, 0x2e, 0xa2, 0x65, 0x18, 0xea, 0xa2, 0x86, 0x3a, 0xd0, 0x98,
0xce, 0xc3, 0xd9, 0xa0, 0x3e, 0xfa, 0xde, 0x00, 0xfc, 0x7b, 0xc4, 0x4b, 0xaa, 0x88, 0x7e, 0x07,
0x74, 0x02, 0x47, 0x1b, 0x3b, 0x5b, 0x31, 0xb2, 0xa5, 0xb8, 0x6d, 0xbc, 0xbb, 0x65, 0x2f, 0x24,
0x5b, 0x7a, 0x08, 0x29, 0x8a, 0x34, 0xc6, 0x9d, 0x5f, 0x20, 0xcb, 0x22, 0x8d, 0xd1, 0x25, 0xb4,
0xa4, 0x79, 0x34, 0xdc, 0x35, 0xc1, 0x9e, 0xde, 0xe9, 0xc5, 0xa3, 0x52, 0x04, 0x7d, 0x84, 0xbe,
0x3d, 0xad, 0x3e, 0xa7, 0x52, 0x71, 0xb1, 0xc3, 0xe0, 0xd5, 0xef, 0x2e, 0xdb, 0xb3, 0x62, 0x2f,
0xad, 0x16, 0x7a, 0x04, 0xfd, 0xfd, 0xaa, 0xae, 0xd4, 0x2e, 0xa7, 0xd8, 0x35, 0x89, 0x7a, 0xfb,
0xee, 0xf5, 0x2e, 0xa7, 0xc8, 0x03, 0x37, 0xa6, 0x72, 0x23, 0xd2, 0x5c, 0xb7, 0xf0, 0x91, 0x4d,
0x7d, 0xd0, 0x42, 0x1f, 0xa0, 0x95, 0x91, 0x35, 0xcd, 0x24, 0xee, 0x19, 0x7b, 0x17, 0xff, 0x68,
0xaf, 0xfa, 0x13, 0xfc, 0x37, 0x46, 0x65, 0xc6, 0x94, 0xd8, 0x45, 0xa5, 0x24, 0x1a, 0x42, 0xe7,
0x2b, 0x11, 0x2c, 0x65, 0x89, 0xc4, 0x7d, 0xaf, 0x3e, 0xee, 0x46, 0xfb, 0x7a, 0xf8, 0x0c, 0xdc,
0x03, 0x0a, 0x1a, 0x40, 0xfd, 0x0b, 0xdd, 0x99, 0x65, 0xef, 0x46, 0xfa, 0x88, 0xee, 0x41, 0xf3,
0x86, 0x64, 0x45, 0xb5, 0xa7, 0xb6, 0x78, 0x5e, 0x3b, 0x75, 0xce, 0xbf, 0xc1, 0xc9, 0x86, 0x6f,
0x6f, 0x37, 0x7a, 0xfe, 0xff, 0xde, 0xa2, 0x5c, 0xe8, 0xcd, 0x5c, 0x38, 0xef, 0x67, 0x25, 0x23,
0xe1, 0x19, 0x61, 0x89, 0xcf, 0x45, 0x12, 0x24, 0x94, 0x99, 0xbd, 0x0d, 0xec, 0x88, 0xe4, 0xa9,
0xfc, 0xcb, 0xa7, 0xe1, 0xac, 0x6a, 0xac, 0x5b, 0x86, 0xf1, 0xe4, 0x67, 0x00, 0x00, 0x00, 0xff,
0xff, 0x83, 0x10, 0x95, 0x5e, 0x4b, 0x04, 0x00, 0x00,
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -10,6 +10,8 @@ It is generated from these files:
google/monitoring/v3/group_service.proto
google/monitoring/v3/metric.proto
google/monitoring/v3/metric_service.proto
google/monitoring/v3/uptime.proto
google/monitoring/v3/uptime_service.proto
It has these top-level messages:
TypedValue
@ -38,6 +40,16 @@ It has these top-level messages:
ListTimeSeriesResponse
CreateTimeSeriesRequest
CreateTimeSeriesError
UptimeCheckConfig
UptimeCheckIp
ListUptimeCheckConfigsRequest
ListUptimeCheckConfigsResponse
GetUptimeCheckConfigRequest
CreateUptimeCheckConfigRequest
UpdateUptimeCheckConfigRequest
DeleteUptimeCheckConfigRequest
ListUptimeCheckIpsRequest
ListUptimeCheckIpsResponse
*/
package monitoring

View File

@ -0,0 +1,748 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: google/monitoring/v3/uptime.proto
package monitoring
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import google_api4 "google.golang.org/genproto/googleapis/api/monitoredres"
import google_protobuf3 "github.com/golang/protobuf/ptypes/duration"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// The regions from which an uptime check can be run.
type UptimeCheckRegion int32
const (
// Default value if no region is specified. Will result in uptime checks
// running from all regions.
UptimeCheckRegion_REGION_UNSPECIFIED UptimeCheckRegion = 0
// Allows checks to run from locations within the United States of America.
UptimeCheckRegion_USA UptimeCheckRegion = 1
// Allows checks to run from locations within the continent of Europe.
UptimeCheckRegion_EUROPE UptimeCheckRegion = 2
// Allows checks to run from locations within the continent of South
// America.
UptimeCheckRegion_SOUTH_AMERICA UptimeCheckRegion = 3
// Allows checks to run from locations within the Asia Pacific area (ex:
// Singapore).
UptimeCheckRegion_ASIA_PACIFIC UptimeCheckRegion = 4
)
var UptimeCheckRegion_name = map[int32]string{
0: "REGION_UNSPECIFIED",
1: "USA",
2: "EUROPE",
3: "SOUTH_AMERICA",
4: "ASIA_PACIFIC",
}
var UptimeCheckRegion_value = map[string]int32{
"REGION_UNSPECIFIED": 0,
"USA": 1,
"EUROPE": 2,
"SOUTH_AMERICA": 3,
"ASIA_PACIFIC": 4,
}
func (x UptimeCheckRegion) String() string {
return proto.EnumName(UptimeCheckRegion_name, int32(x))
}
func (UptimeCheckRegion) EnumDescriptor() ([]byte, []int) { return fileDescriptor5, []int{0} }
// The supported resource types that can be used as values of
// group_resource.resource_type. gae_app and uptime_url are not allowed
// because group checks on App Engine modules and URLs are not allowed.
type GroupResourceType int32
const (
// Default value (not valid).
GroupResourceType_RESOURCE_TYPE_UNSPECIFIED GroupResourceType = 0
// A group of instances (could be either GCE or AWS_EC2).
GroupResourceType_INSTANCE GroupResourceType = 1
// A group of AWS load balancers.
GroupResourceType_AWS_ELB_LOAD_BALANCER GroupResourceType = 2
)
var GroupResourceType_name = map[int32]string{
0: "RESOURCE_TYPE_UNSPECIFIED",
1: "INSTANCE",
2: "AWS_ELB_LOAD_BALANCER",
}
var GroupResourceType_value = map[string]int32{
"RESOURCE_TYPE_UNSPECIFIED": 0,
"INSTANCE": 1,
"AWS_ELB_LOAD_BALANCER": 2,
}
func (x GroupResourceType) String() string {
return proto.EnumName(GroupResourceType_name, int32(x))
}
func (GroupResourceType) EnumDescriptor() ([]byte, []int) { return fileDescriptor5, []int{1} }
// This message configures which resources and services to monitor for
// availability.
type UptimeCheckConfig struct {
// A unique resource name for this UptimeCheckConfig. The format is:
//
//
// `projects/[PROJECT_ID]/uptimeCheckConfigs/[UPTIME_CHECK_ID]`.
//
// This field should be omitted when creating the uptime check configuration;
// on create, the resource name is assigned by the server and included in the
// response.
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
// A human-friendly name for the uptime check configuration. The display name
// should be unique within a Stackdriver Account in order to make it easier
// to identify; however, uniqueness is not enforced. Required.
DisplayName string `protobuf:"bytes,2,opt,name=display_name,json=displayName" json:"display_name,omitempty"`
// The resource the check is checking. Required.
//
// Types that are valid to be assigned to Resource:
// *UptimeCheckConfig_MonitoredResource
// *UptimeCheckConfig_ResourceGroup_
Resource isUptimeCheckConfig_Resource `protobuf_oneof:"resource"`
// The type of uptime check request.
//
// Types that are valid to be assigned to CheckRequestType:
// *UptimeCheckConfig_HttpCheck_
// *UptimeCheckConfig_TcpCheck_
CheckRequestType isUptimeCheckConfig_CheckRequestType `protobuf_oneof:"check_request_type"`
// How often the uptime check is performed.
// Currently, only 1, 5, 10, and 15 minutes are supported. Required.
Period *google_protobuf3.Duration `protobuf:"bytes,7,opt,name=period" json:"period,omitempty"`
// The maximum amount of time to wait for the request to complete (must be
// between 1 and 60 seconds). Required.
Timeout *google_protobuf3.Duration `protobuf:"bytes,8,opt,name=timeout" json:"timeout,omitempty"`
// The expected content on the page the check is run against.
// Currently, only the first entry in the list is supported, and other entries
// will be ignored. The server will look for an exact match of the string in
// the page response's content. This field is optional and should only be
// specified if a content match is required.
ContentMatchers []*UptimeCheckConfig_ContentMatcher `protobuf:"bytes,9,rep,name=content_matchers,json=contentMatchers" json:"content_matchers,omitempty"`
// The list of regions from which the check will be run.
// If this field is specified, enough regions to include a minimum of
// 3 locations must be provided, or an error message is returned.
// Not specifying this field will result in uptime checks running from all
// regions.
SelectedRegions []UptimeCheckRegion `protobuf:"varint,10,rep,packed,name=selected_regions,json=selectedRegions,enum=google.monitoring.v3.UptimeCheckRegion" json:"selected_regions,omitempty"`
// The internal checkers that this check will egress from.
InternalCheckers []*UptimeCheckConfig_InternalChecker `protobuf:"bytes,14,rep,name=internal_checkers,json=internalCheckers" json:"internal_checkers,omitempty"`
}
func (m *UptimeCheckConfig) Reset() { *m = UptimeCheckConfig{} }
func (m *UptimeCheckConfig) String() string { return proto.CompactTextString(m) }
func (*UptimeCheckConfig) ProtoMessage() {}
func (*UptimeCheckConfig) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{0} }
type isUptimeCheckConfig_Resource interface {
isUptimeCheckConfig_Resource()
}
type isUptimeCheckConfig_CheckRequestType interface {
isUptimeCheckConfig_CheckRequestType()
}
type UptimeCheckConfig_MonitoredResource struct {
MonitoredResource *google_api4.MonitoredResource `protobuf:"bytes,3,opt,name=monitored_resource,json=monitoredResource,oneof"`
}
type UptimeCheckConfig_ResourceGroup_ struct {
ResourceGroup *UptimeCheckConfig_ResourceGroup `protobuf:"bytes,4,opt,name=resource_group,json=resourceGroup,oneof"`
}
type UptimeCheckConfig_HttpCheck_ struct {
HttpCheck *UptimeCheckConfig_HttpCheck `protobuf:"bytes,5,opt,name=http_check,json=httpCheck,oneof"`
}
type UptimeCheckConfig_TcpCheck_ struct {
TcpCheck *UptimeCheckConfig_TcpCheck `protobuf:"bytes,6,opt,name=tcp_check,json=tcpCheck,oneof"`
}
func (*UptimeCheckConfig_MonitoredResource) isUptimeCheckConfig_Resource() {}
func (*UptimeCheckConfig_ResourceGroup_) isUptimeCheckConfig_Resource() {}
func (*UptimeCheckConfig_HttpCheck_) isUptimeCheckConfig_CheckRequestType() {}
func (*UptimeCheckConfig_TcpCheck_) isUptimeCheckConfig_CheckRequestType() {}
func (m *UptimeCheckConfig) GetResource() isUptimeCheckConfig_Resource {
if m != nil {
return m.Resource
}
return nil
}
func (m *UptimeCheckConfig) GetCheckRequestType() isUptimeCheckConfig_CheckRequestType {
if m != nil {
return m.CheckRequestType
}
return nil
}
func (m *UptimeCheckConfig) GetName() string {
if m != nil {
return m.Name
}
return ""
}
func (m *UptimeCheckConfig) GetDisplayName() string {
if m != nil {
return m.DisplayName
}
return ""
}
func (m *UptimeCheckConfig) GetMonitoredResource() *google_api4.MonitoredResource {
if x, ok := m.GetResource().(*UptimeCheckConfig_MonitoredResource); ok {
return x.MonitoredResource
}
return nil
}
func (m *UptimeCheckConfig) GetResourceGroup() *UptimeCheckConfig_ResourceGroup {
if x, ok := m.GetResource().(*UptimeCheckConfig_ResourceGroup_); ok {
return x.ResourceGroup
}
return nil
}
func (m *UptimeCheckConfig) GetHttpCheck() *UptimeCheckConfig_HttpCheck {
if x, ok := m.GetCheckRequestType().(*UptimeCheckConfig_HttpCheck_); ok {
return x.HttpCheck
}
return nil
}
func (m *UptimeCheckConfig) GetTcpCheck() *UptimeCheckConfig_TcpCheck {
if x, ok := m.GetCheckRequestType().(*UptimeCheckConfig_TcpCheck_); ok {
return x.TcpCheck
}
return nil
}
func (m *UptimeCheckConfig) GetPeriod() *google_protobuf3.Duration {
if m != nil {
return m.Period
}
return nil
}
func (m *UptimeCheckConfig) GetTimeout() *google_protobuf3.Duration {
if m != nil {
return m.Timeout
}
return nil
}
func (m *UptimeCheckConfig) GetContentMatchers() []*UptimeCheckConfig_ContentMatcher {
if m != nil {
return m.ContentMatchers
}
return nil
}
func (m *UptimeCheckConfig) GetSelectedRegions() []UptimeCheckRegion {
if m != nil {
return m.SelectedRegions
}
return nil
}
func (m *UptimeCheckConfig) GetInternalCheckers() []*UptimeCheckConfig_InternalChecker {
if m != nil {
return m.InternalCheckers
}
return nil
}
// XXX_OneofFuncs is for the internal use of the proto package.
func (*UptimeCheckConfig) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
return _UptimeCheckConfig_OneofMarshaler, _UptimeCheckConfig_OneofUnmarshaler, _UptimeCheckConfig_OneofSizer, []interface{}{
(*UptimeCheckConfig_MonitoredResource)(nil),
(*UptimeCheckConfig_ResourceGroup_)(nil),
(*UptimeCheckConfig_HttpCheck_)(nil),
(*UptimeCheckConfig_TcpCheck_)(nil),
}
}
func _UptimeCheckConfig_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
m := msg.(*UptimeCheckConfig)
// resource
switch x := m.Resource.(type) {
case *UptimeCheckConfig_MonitoredResource:
b.EncodeVarint(3<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.MonitoredResource); err != nil {
return err
}
case *UptimeCheckConfig_ResourceGroup_:
b.EncodeVarint(4<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.ResourceGroup); err != nil {
return err
}
case nil:
default:
return fmt.Errorf("UptimeCheckConfig.Resource has unexpected type %T", x)
}
// check_request_type
switch x := m.CheckRequestType.(type) {
case *UptimeCheckConfig_HttpCheck_:
b.EncodeVarint(5<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.HttpCheck); err != nil {
return err
}
case *UptimeCheckConfig_TcpCheck_:
b.EncodeVarint(6<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.TcpCheck); err != nil {
return err
}
case nil:
default:
return fmt.Errorf("UptimeCheckConfig.CheckRequestType has unexpected type %T", x)
}
return nil
}
func _UptimeCheckConfig_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
m := msg.(*UptimeCheckConfig)
switch tag {
case 3: // resource.monitored_resource
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(google_api4.MonitoredResource)
err := b.DecodeMessage(msg)
m.Resource = &UptimeCheckConfig_MonitoredResource{msg}
return true, err
case 4: // resource.resource_group
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(UptimeCheckConfig_ResourceGroup)
err := b.DecodeMessage(msg)
m.Resource = &UptimeCheckConfig_ResourceGroup_{msg}
return true, err
case 5: // check_request_type.http_check
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(UptimeCheckConfig_HttpCheck)
err := b.DecodeMessage(msg)
m.CheckRequestType = &UptimeCheckConfig_HttpCheck_{msg}
return true, err
case 6: // check_request_type.tcp_check
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(UptimeCheckConfig_TcpCheck)
err := b.DecodeMessage(msg)
m.CheckRequestType = &UptimeCheckConfig_TcpCheck_{msg}
return true, err
default:
return false, nil
}
}
func _UptimeCheckConfig_OneofSizer(msg proto.Message) (n int) {
m := msg.(*UptimeCheckConfig)
// resource
switch x := m.Resource.(type) {
case *UptimeCheckConfig_MonitoredResource:
s := proto.Size(x.MonitoredResource)
n += proto.SizeVarint(3<<3 | proto.WireBytes)
n += proto.SizeVarint(uint64(s))
n += s
case *UptimeCheckConfig_ResourceGroup_:
s := proto.Size(x.ResourceGroup)
n += proto.SizeVarint(4<<3 | proto.WireBytes)
n += proto.SizeVarint(uint64(s))
n += s
case nil:
default:
panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
}
// check_request_type
switch x := m.CheckRequestType.(type) {
case *UptimeCheckConfig_HttpCheck_:
s := proto.Size(x.HttpCheck)
n += proto.SizeVarint(5<<3 | proto.WireBytes)
n += proto.SizeVarint(uint64(s))
n += s
case *UptimeCheckConfig_TcpCheck_:
s := proto.Size(x.TcpCheck)
n += proto.SizeVarint(6<<3 | proto.WireBytes)
n += proto.SizeVarint(uint64(s))
n += s
case nil:
default:
panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
}
return n
}
// The resource submessage for group checks. It can be used instead of a
// monitored resource, when multiple resources are being monitored.
type UptimeCheckConfig_ResourceGroup struct {
// The group of resources being monitored. Should be only the
// group_id, not projects/<project_id>/groups/<group_id>.
GroupId string `protobuf:"bytes,1,opt,name=group_id,json=groupId" json:"group_id,omitempty"`
// The resource type of the group members.
ResourceType GroupResourceType `protobuf:"varint,2,opt,name=resource_type,json=resourceType,enum=google.monitoring.v3.GroupResourceType" json:"resource_type,omitempty"`
}
func (m *UptimeCheckConfig_ResourceGroup) Reset() { *m = UptimeCheckConfig_ResourceGroup{} }
func (m *UptimeCheckConfig_ResourceGroup) String() string { return proto.CompactTextString(m) }
func (*UptimeCheckConfig_ResourceGroup) ProtoMessage() {}
func (*UptimeCheckConfig_ResourceGroup) Descriptor() ([]byte, []int) {
return fileDescriptor5, []int{0, 0}
}
func (m *UptimeCheckConfig_ResourceGroup) GetGroupId() string {
if m != nil {
return m.GroupId
}
return ""
}
func (m *UptimeCheckConfig_ResourceGroup) GetResourceType() GroupResourceType {
if m != nil {
return m.ResourceType
}
return GroupResourceType_RESOURCE_TYPE_UNSPECIFIED
}
// Information involved in an HTTP/HTTPS uptime check request.
type UptimeCheckConfig_HttpCheck struct {
// If true, use HTTPS instead of HTTP to run the check.
UseSsl bool `protobuf:"varint,1,opt,name=use_ssl,json=useSsl" json:"use_ssl,omitempty"`
// The path to the page to run the check against. Will be combined with the
// host (specified within the MonitoredResource) and port to construct the
// full URL. Optional (defaults to "/").
Path string `protobuf:"bytes,2,opt,name=path" json:"path,omitempty"`
// The port to the page to run the check against. Will be combined with host
// (specified within the MonitoredResource) and path to construct the full
// URL. Optional (defaults to 80 without SSL, or 443 with SSL).
Port int32 `protobuf:"varint,3,opt,name=port" json:"port,omitempty"`
// The authentication information. Optional when creating an HTTP check;
// defaults to empty.
AuthInfo *UptimeCheckConfig_HttpCheck_BasicAuthentication `protobuf:"bytes,4,opt,name=auth_info,json=authInfo" json:"auth_info,omitempty"`
// Boolean specifiying whether to encrypt the header information.
// Encryption should be specified for any headers related to authentication
// that you do not wish to be seen when retrieving the configuration. The
// server will be responsible for encrypting the headers.
// On Get/List calls, if mask_headers is set to True then the headers
// will be obscured with ******.
MaskHeaders bool `protobuf:"varint,5,opt,name=mask_headers,json=maskHeaders" json:"mask_headers,omitempty"`
// The list of headers to send as part of the uptime check request.
// If two headers have the same key and different values, they should
// be entered as a single header, with the value being a comma-separated
// list of all the desired values as described at
// https://www.w3.org/Protocols/rfc2616/rfc2616.txt (page 31).
// Entering two separate headers with the same key in a Create call will
// cause the first to be overwritten by the second.
Headers map[string]string `protobuf:"bytes,6,rep,name=headers" json:"headers,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
}
func (m *UptimeCheckConfig_HttpCheck) Reset() { *m = UptimeCheckConfig_HttpCheck{} }
func (m *UptimeCheckConfig_HttpCheck) String() string { return proto.CompactTextString(m) }
func (*UptimeCheckConfig_HttpCheck) ProtoMessage() {}
func (*UptimeCheckConfig_HttpCheck) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{0, 1} }
func (m *UptimeCheckConfig_HttpCheck) GetUseSsl() bool {
if m != nil {
return m.UseSsl
}
return false
}
func (m *UptimeCheckConfig_HttpCheck) GetPath() string {
if m != nil {
return m.Path
}
return ""
}
func (m *UptimeCheckConfig_HttpCheck) GetPort() int32 {
if m != nil {
return m.Port
}
return 0
}
func (m *UptimeCheckConfig_HttpCheck) GetAuthInfo() *UptimeCheckConfig_HttpCheck_BasicAuthentication {
if m != nil {
return m.AuthInfo
}
return nil
}
func (m *UptimeCheckConfig_HttpCheck) GetMaskHeaders() bool {
if m != nil {
return m.MaskHeaders
}
return false
}
func (m *UptimeCheckConfig_HttpCheck) GetHeaders() map[string]string {
if m != nil {
return m.Headers
}
return nil
}
// A type of authentication to perform against the specified resource or URL
// that uses username and password.
// Currently, only Basic authentication is supported in Uptime Monitoring.
type UptimeCheckConfig_HttpCheck_BasicAuthentication struct {
// The username to authenticate.
Username string `protobuf:"bytes,1,opt,name=username" json:"username,omitempty"`
// The password to authenticate.
Password string `protobuf:"bytes,2,opt,name=password" json:"password,omitempty"`
}
func (m *UptimeCheckConfig_HttpCheck_BasicAuthentication) Reset() {
*m = UptimeCheckConfig_HttpCheck_BasicAuthentication{}
}
func (m *UptimeCheckConfig_HttpCheck_BasicAuthentication) String() string {
return proto.CompactTextString(m)
}
func (*UptimeCheckConfig_HttpCheck_BasicAuthentication) ProtoMessage() {}
func (*UptimeCheckConfig_HttpCheck_BasicAuthentication) Descriptor() ([]byte, []int) {
return fileDescriptor5, []int{0, 1, 0}
}
func (m *UptimeCheckConfig_HttpCheck_BasicAuthentication) GetUsername() string {
if m != nil {
return m.Username
}
return ""
}
func (m *UptimeCheckConfig_HttpCheck_BasicAuthentication) GetPassword() string {
if m != nil {
return m.Password
}
return ""
}
// Information required for a TCP uptime check request.
type UptimeCheckConfig_TcpCheck struct {
// The port to the page to run the check against. Will be combined with host
// (specified within the MonitoredResource) to construct the full URL.
// Required.
Port int32 `protobuf:"varint,1,opt,name=port" json:"port,omitempty"`
}
func (m *UptimeCheckConfig_TcpCheck) Reset() { *m = UptimeCheckConfig_TcpCheck{} }
func (m *UptimeCheckConfig_TcpCheck) String() string { return proto.CompactTextString(m) }
func (*UptimeCheckConfig_TcpCheck) ProtoMessage() {}
func (*UptimeCheckConfig_TcpCheck) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{0, 2} }
func (m *UptimeCheckConfig_TcpCheck) GetPort() int32 {
if m != nil {
return m.Port
}
return 0
}
// Used to perform string matching. Currently, this matches on the exact
// content. In the future, it can be expanded to allow for regular expressions
// and more complex matching.
type UptimeCheckConfig_ContentMatcher struct {
// String content to match
Content string `protobuf:"bytes,1,opt,name=content" json:"content,omitempty"`
}
func (m *UptimeCheckConfig_ContentMatcher) Reset() { *m = UptimeCheckConfig_ContentMatcher{} }
func (m *UptimeCheckConfig_ContentMatcher) String() string { return proto.CompactTextString(m) }
func (*UptimeCheckConfig_ContentMatcher) ProtoMessage() {}
func (*UptimeCheckConfig_ContentMatcher) Descriptor() ([]byte, []int) {
return fileDescriptor5, []int{0, 3}
}
func (m *UptimeCheckConfig_ContentMatcher) GetContent() string {
if m != nil {
return m.Content
}
return ""
}
// Nimbus InternalCheckers.
type UptimeCheckConfig_InternalChecker struct {
// The GCP project ID. Not necessarily the same as the project_id for the config.
ProjectId string `protobuf:"bytes,1,opt,name=project_id,json=projectId" json:"project_id,omitempty"`
// The internal network to perform this uptime check on.
Network string `protobuf:"bytes,2,opt,name=network" json:"network,omitempty"`
// The GCP zone the uptime check should egress from. Only respected for
// internal uptime checks, where internal_network is specified.
GcpZone string `protobuf:"bytes,3,opt,name=gcp_zone,json=gcpZone" json:"gcp_zone,omitempty"`
// The checker ID.
CheckerId string `protobuf:"bytes,4,opt,name=checker_id,json=checkerId" json:"checker_id,omitempty"`
// The checker's human-readable name.
DisplayName string `protobuf:"bytes,5,opt,name=display_name,json=displayName" json:"display_name,omitempty"`
}
func (m *UptimeCheckConfig_InternalChecker) Reset() { *m = UptimeCheckConfig_InternalChecker{} }
func (m *UptimeCheckConfig_InternalChecker) String() string { return proto.CompactTextString(m) }
func (*UptimeCheckConfig_InternalChecker) ProtoMessage() {}
func (*UptimeCheckConfig_InternalChecker) Descriptor() ([]byte, []int) {
return fileDescriptor5, []int{0, 4}
}
func (m *UptimeCheckConfig_InternalChecker) GetProjectId() string {
if m != nil {
return m.ProjectId
}
return ""
}
func (m *UptimeCheckConfig_InternalChecker) GetNetwork() string {
if m != nil {
return m.Network
}
return ""
}
func (m *UptimeCheckConfig_InternalChecker) GetGcpZone() string {
if m != nil {
return m.GcpZone
}
return ""
}
func (m *UptimeCheckConfig_InternalChecker) GetCheckerId() string {
if m != nil {
return m.CheckerId
}
return ""
}
func (m *UptimeCheckConfig_InternalChecker) GetDisplayName() string {
if m != nil {
return m.DisplayName
}
return ""
}
// Contains the region, location, and list of IP
// addresses where checkers in the location run from.
type UptimeCheckIp struct {
// A broad region category in which the IP address is located.
Region UptimeCheckRegion `protobuf:"varint,1,opt,name=region,enum=google.monitoring.v3.UptimeCheckRegion" json:"region,omitempty"`
// A more specific location within the region that typically encodes
// a particular city/town/metro (and its containing state/province or country)
// within the broader umbrella region category.
Location string `protobuf:"bytes,2,opt,name=location" json:"location,omitempty"`
// The IP address from which the uptime check originates. This is a full
// IP address (not an IP address range). Most IP addresses, as of this
// publication, are in IPv4 format; however, one should not rely on the
// IP addresses being in IPv4 format indefinitely and should support
// interpreting this field in either IPv4 or IPv6 format.
IpAddress string `protobuf:"bytes,3,opt,name=ip_address,json=ipAddress" json:"ip_address,omitempty"`
}
func (m *UptimeCheckIp) Reset() { *m = UptimeCheckIp{} }
func (m *UptimeCheckIp) String() string { return proto.CompactTextString(m) }
func (*UptimeCheckIp) ProtoMessage() {}
func (*UptimeCheckIp) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{1} }
func (m *UptimeCheckIp) GetRegion() UptimeCheckRegion {
if m != nil {
return m.Region
}
return UptimeCheckRegion_REGION_UNSPECIFIED
}
func (m *UptimeCheckIp) GetLocation() string {
if m != nil {
return m.Location
}
return ""
}
func (m *UptimeCheckIp) GetIpAddress() string {
if m != nil {
return m.IpAddress
}
return ""
}
func init() {
proto.RegisterType((*UptimeCheckConfig)(nil), "google.monitoring.v3.UptimeCheckConfig")
proto.RegisterType((*UptimeCheckConfig_ResourceGroup)(nil), "google.monitoring.v3.UptimeCheckConfig.ResourceGroup")
proto.RegisterType((*UptimeCheckConfig_HttpCheck)(nil), "google.monitoring.v3.UptimeCheckConfig.HttpCheck")
proto.RegisterType((*UptimeCheckConfig_HttpCheck_BasicAuthentication)(nil), "google.monitoring.v3.UptimeCheckConfig.HttpCheck.BasicAuthentication")
proto.RegisterType((*UptimeCheckConfig_TcpCheck)(nil), "google.monitoring.v3.UptimeCheckConfig.TcpCheck")
proto.RegisterType((*UptimeCheckConfig_ContentMatcher)(nil), "google.monitoring.v3.UptimeCheckConfig.ContentMatcher")
proto.RegisterType((*UptimeCheckConfig_InternalChecker)(nil), "google.monitoring.v3.UptimeCheckConfig.InternalChecker")
proto.RegisterType((*UptimeCheckIp)(nil), "google.monitoring.v3.UptimeCheckIp")
proto.RegisterEnum("google.monitoring.v3.UptimeCheckRegion", UptimeCheckRegion_name, UptimeCheckRegion_value)
proto.RegisterEnum("google.monitoring.v3.GroupResourceType", GroupResourceType_name, GroupResourceType_value)
}
func init() { proto.RegisterFile("google/monitoring/v3/uptime.proto", fileDescriptor5) }
var fileDescriptor5 = []byte{
// 1021 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x56, 0xdd, 0x4e, 0xe3, 0x46,
0x14, 0x5e, 0x13, 0xc8, 0xcf, 0x21, 0xb0, 0x66, 0x4a, 0xdb, 0x60, 0x89, 0x15, 0xbb, 0xbd, 0x28,
0xe2, 0xc2, 0xe9, 0x12, 0xf5, 0x47, 0x5b, 0x69, 0x2b, 0x27, 0xb8, 0xc4, 0x12, 0x24, 0xd1, 0x84,
0x6c, 0xdb, 0x2d, 0xaa, 0x65, 0xec, 0x21, 0x71, 0x49, 0x3c, 0xae, 0x67, 0xcc, 0x96, 0xbe, 0x42,
0x1f, 0xa3, 0x17, 0x95, 0xfa, 0x04, 0x7d, 0x86, 0xbe, 0x4d, 0xdf, 0xa0, 0x9a, 0xf1, 0x4c, 0x20,
0x40, 0xb5, 0x70, 0x37, 0xdf, 0xf9, 0xf9, 0xe6, 0x1c, 0x9f, 0x9f, 0x31, 0x3c, 0x1f, 0x53, 0x3a,
0x9e, 0x92, 0xe6, 0x8c, 0x26, 0x31, 0xa7, 0x59, 0x9c, 0x8c, 0x9b, 0x97, 0xad, 0x66, 0x9e, 0xf2,
0x78, 0x46, 0xec, 0x34, 0xa3, 0x9c, 0xa2, 0xcd, 0xc2, 0xc4, 0xbe, 0x36, 0xb1, 0x2f, 0x5b, 0xd6,
0x27, 0xca, 0x31, 0x48, 0x63, 0xed, 0x4c, 0x22, 0x3f, 0x23, 0x8c, 0xe6, 0x59, 0xa8, 0x5c, 0xad,
0x67, 0xca, 0x48, 0xa2, 0xb3, 0xfc, 0xbc, 0x19, 0xe5, 0x59, 0xc0, 0x63, 0x9a, 0x14, 0xfa, 0x17,
0xff, 0xd6, 0x61, 0x63, 0x24, 0xef, 0xea, 0x4c, 0x48, 0x78, 0xd1, 0xa1, 0xc9, 0x79, 0x3c, 0x46,
0x08, 0x96, 0x93, 0x60, 0x46, 0x1a, 0xc6, 0x8e, 0xb1, 0x5b, 0xc3, 0xf2, 0x8c, 0x9e, 0x43, 0x3d,
0x8a, 0x59, 0x3a, 0x0d, 0xae, 0x7c, 0xa9, 0x5b, 0x92, 0xba, 0x55, 0x25, 0xeb, 0x09, 0x93, 0x1e,
0xa0, 0xbb, 0x81, 0x34, 0x4a, 0x3b, 0xc6, 0xee, 0xea, 0xfe, 0xb6, 0xad, 0x92, 0x08, 0xd2, 0xd8,
0x3e, 0xd6, 0x56, 0x58, 0x19, 0x75, 0x9f, 0xe0, 0x8d, 0xd9, 0x6d, 0x21, 0xfa, 0x09, 0xd6, 0x35,
0x8b, 0x3f, 0xce, 0x68, 0x9e, 0x36, 0x96, 0x25, 0xd7, 0xe7, 0xf6, 0x7d, 0x1f, 0xc4, 0xbe, 0x93,
0x87, 0xad, 0x99, 0x0e, 0x85, 0x73, 0xf7, 0x09, 0x5e, 0xcb, 0x6e, 0x0a, 0x10, 0x06, 0x98, 0x70,
0x9e, 0xfa, 0xa1, 0x70, 0x69, 0xac, 0x48, 0xee, 0x97, 0x0f, 0xe5, 0xee, 0x72, 0x9e, 0x4a, 0xdc,
0x35, 0x70, 0x6d, 0xa2, 0x01, 0xea, 0x43, 0x8d, 0x87, 0x9a, 0xb2, 0x2c, 0x29, 0x3f, 0x7b, 0x28,
0xe5, 0x49, 0x38, 0x67, 0xac, 0x72, 0x75, 0x46, 0x2f, 0xa1, 0x9c, 0x92, 0x2c, 0xa6, 0x51, 0xa3,
0x22, 0xd9, 0xb6, 0x34, 0x9b, 0x2e, 0xa9, 0x7d, 0xa0, 0x4a, 0x8a, 0x95, 0x21, 0x6a, 0x41, 0x45,
0x50, 0xd3, 0x9c, 0x37, 0xaa, 0xef, 0xf3, 0xd1, 0x96, 0x28, 0x00, 0x33, 0xa4, 0x09, 0x27, 0x09,
0xf7, 0x67, 0x01, 0x0f, 0x27, 0x24, 0x63, 0x8d, 0xda, 0x4e, 0x69, 0x77, 0x75, 0xff, 0x8b, 0x87,
0xc6, 0xdf, 0x29, 0xfc, 0x8f, 0x0b, 0x77, 0xfc, 0x34, 0x5c, 0xc0, 0x0c, 0x61, 0x30, 0x19, 0x99,
0x92, 0x90, 0xcb, 0xf6, 0x18, 0xc7, 0x34, 0x61, 0x0d, 0xd8, 0x29, 0xed, 0xae, 0xef, 0x7f, 0xfa,
0xde, 0x2b, 0xb0, 0xb4, 0xc7, 0x4f, 0x35, 0x41, 0x81, 0x19, 0x8a, 0x60, 0x23, 0x4e, 0x38, 0xc9,
0x92, 0x60, 0x5a, 0x7c, 0x74, 0x11, 0xf7, 0xba, 0x8c, 0xfb, 0xcb, 0x87, 0xc6, 0xed, 0x29, 0x82,
0x4e, 0xe1, 0x8f, 0xcd, 0x78, 0x51, 0xc0, 0xac, 0x5f, 0x61, 0x6d, 0xa1, 0x97, 0xd0, 0x16, 0x54,
0x65, 0x47, 0xfa, 0x71, 0xa4, 0xa6, 0xa4, 0x22, 0xb1, 0x17, 0xa1, 0x23, 0x98, 0xb7, 0x99, 0xcf,
0xaf, 0xd2, 0x62, 0x52, 0xfe, 0x37, 0x45, 0x49, 0xa7, 0xb9, 0x4f, 0xae, 0x52, 0x82, 0xeb, 0xd9,
0x0d, 0x64, 0xfd, 0x5d, 0x82, 0xda, 0xbc, 0xd5, 0xd0, 0xc7, 0x50, 0xc9, 0x19, 0xf1, 0x19, 0x9b,
0xca, 0x5b, 0xab, 0xb8, 0x9c, 0x33, 0x32, 0x64, 0x53, 0x31, 0xb1, 0x69, 0xc0, 0x27, 0x6a, 0x2a,
0xe5, 0x59, 0xca, 0x68, 0xc6, 0xe5, 0x00, 0xae, 0x60, 0x79, 0x46, 0x67, 0x50, 0x0b, 0x72, 0x3e,
0xf1, 0xe3, 0xe4, 0x9c, 0xaa, 0x69, 0x72, 0x1f, 0xdd, 0xf1, 0x76, 0x3b, 0x60, 0x71, 0xe8, 0xe4,
0x7c, 0x42, 0x12, 0x1e, 0x87, 0x45, 0x23, 0x55, 0x05, 0xaf, 0x97, 0x9c, 0x53, 0xb1, 0x29, 0x66,
0x01, 0xbb, 0xf0, 0x27, 0x24, 0x88, 0x44, 0x35, 0x56, 0x64, 0xa4, 0xab, 0x42, 0xd6, 0x2d, 0x44,
0xe8, 0x7b, 0xa8, 0x68, 0x6d, 0x59, 0xd6, 0xea, 0xf5, 0xe3, 0x83, 0x50, 0x5c, 0x6e, 0xc2, 0xb3,
0x2b, 0xac, 0xe9, 0xac, 0x63, 0xf8, 0xe0, 0x9e, 0xe8, 0x90, 0x05, 0xd5, 0x9c, 0x89, 0x9a, 0xce,
0xb7, 0xda, 0x1c, 0x0b, 0x5d, 0x1a, 0x30, 0xf6, 0x8e, 0x66, 0x91, 0xfa, 0x7e, 0x73, 0x6c, 0xbd,
0x82, 0xfa, 0xcd, 0x7b, 0x90, 0x09, 0xa5, 0x0b, 0x72, 0xa5, 0x28, 0xc4, 0x11, 0x6d, 0xc2, 0xca,
0x65, 0x30, 0xcd, 0xf5, 0x42, 0x2c, 0xc0, 0xab, 0xa5, 0xaf, 0x0c, 0xeb, 0x19, 0x54, 0xf5, 0x44,
0xcf, 0x6b, 0x61, 0x5c, 0xd7, 0xc2, 0xda, 0x83, 0xf5, 0xc5, 0x89, 0x41, 0x0d, 0xa8, 0xa8, 0x99,
0xd1, 0x4d, 0xa5, 0xa0, 0xf5, 0xa7, 0x01, 0x4f, 0x6f, 0xb5, 0x29, 0xda, 0x06, 0x48, 0x33, 0xfa,
0x33, 0x09, 0xf9, 0x75, 0x17, 0xd6, 0x94, 0xc4, 0x8b, 0x04, 0x59, 0x42, 0xf8, 0x3b, 0x9a, 0x5d,
0xa8, 0xd0, 0x34, 0x94, 0xcd, 0x1b, 0xa6, 0xfe, 0x6f, 0x34, 0x29, 0xb6, 0xb3, 0x68, 0xde, 0x30,
0x7d, 0x4b, 0x13, 0x22, 0x38, 0xd5, 0x14, 0x09, 0xce, 0xe5, 0x82, 0x53, 0x49, 0xbc, 0xe8, 0xce,
0x23, 0xb0, 0x72, 0xe7, 0x11, 0x68, 0x03, 0x54, 0x75, 0x03, 0xb7, 0x37, 0x01, 0x49, 0x5f, 0x3f,
0x23, 0xbf, 0xe4, 0x84, 0x71, 0x39, 0x0f, 0x2f, 0x7e, 0x37, 0x60, 0xed, 0x46, 0x61, 0xbd, 0x14,
0x7d, 0x03, 0xe5, 0x62, 0x1f, 0xc8, 0x2c, 0x1e, 0xb1, 0x0e, 0x94, 0x9b, 0x28, 0xe1, 0x94, 0x16,
0xa5, 0xd6, 0x25, 0xd4, 0x58, 0xa4, 0x14, 0xa7, 0x7e, 0x10, 0x45, 0x19, 0x61, 0x4c, 0xe5, 0x5b,
0x8b, 0x53, 0xa7, 0x10, 0xec, 0x91, 0x85, 0x07, 0xb0, 0xe0, 0x45, 0x1f, 0x01, 0xc2, 0xee, 0xa1,
0xd7, 0xef, 0xf9, 0xa3, 0xde, 0x70, 0xe0, 0x76, 0xbc, 0x6f, 0x3d, 0xf7, 0xc0, 0x7c, 0x82, 0x2a,
0x50, 0x1a, 0x0d, 0x1d, 0xd3, 0x40, 0x00, 0x65, 0x77, 0x84, 0xfb, 0x03, 0xd7, 0x5c, 0x42, 0x1b,
0xb0, 0x36, 0xec, 0x8f, 0x4e, 0xba, 0xbe, 0x73, 0xec, 0x62, 0xaf, 0xe3, 0x98, 0x25, 0x64, 0x42,
0xdd, 0x19, 0x7a, 0x8e, 0x3f, 0x70, 0x84, 0x6b, 0xc7, 0x5c, 0xde, 0xfb, 0x11, 0x36, 0xee, 0x8c,
0x3a, 0xda, 0x86, 0x2d, 0xec, 0x0e, 0xfb, 0x23, 0xdc, 0x71, 0xfd, 0x93, 0x1f, 0x06, 0xee, 0xad,
0xdb, 0xea, 0x50, 0xf5, 0x7a, 0xc3, 0x13, 0xa7, 0xd7, 0x71, 0x4d, 0x03, 0x6d, 0xc1, 0x87, 0xce,
0x77, 0x43, 0xdf, 0x3d, 0x6a, 0xfb, 0x47, 0x7d, 0xe7, 0xc0, 0x6f, 0x3b, 0x47, 0x42, 0x83, 0xcd,
0xa5, 0xf6, 0x1f, 0x06, 0x34, 0x42, 0x3a, 0xbb, 0xf7, 0xab, 0xb5, 0x57, 0x8b, 0xf4, 0x06, 0x62,
0xf5, 0x0f, 0x8c, 0xb7, 0xaf, 0x95, 0xd1, 0x98, 0x4e, 0x83, 0x64, 0x6c, 0xd3, 0x6c, 0xdc, 0x1c,
0x93, 0x44, 0x3e, 0x0c, 0xcd, 0x42, 0x15, 0xa4, 0x31, 0x5b, 0xfc, 0x1d, 0xf9, 0xfa, 0x1a, 0xfd,
0xb5, 0x64, 0x1d, 0x16, 0x04, 0x9d, 0x29, 0xcd, 0x23, 0xfd, 0x94, 0x8b, 0xbb, 0xde, 0xb4, 0xfe,
0xd1, 0xca, 0x53, 0xa9, 0x3c, 0xbd, 0x56, 0x9e, 0xbe, 0x69, 0x9d, 0x95, 0xe5, 0x25, 0xad, 0xff,
0x02, 0x00, 0x00, 0xff, 0xff, 0xc9, 0xa5, 0xbc, 0x87, 0xf2, 0x08, 0x00, 0x00,
}

View File

@ -0,0 +1,591 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: google/monitoring/v3/uptime_service.proto
package monitoring
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import _ "google.golang.org/genproto/googleapis/api/annotations"
import google_protobuf4 "github.com/golang/protobuf/ptypes/empty"
import google_protobuf5 "google.golang.org/genproto/protobuf/field_mask"
import (
context "golang.org/x/net/context"
grpc "google.golang.org/grpc"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// The protocol for the `ListUptimeCheckConfigs` request.
type ListUptimeCheckConfigsRequest struct {
// The project whose uptime check configurations are listed. The format is
//
// `projects/[PROJECT_ID]`.
Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"`
// The maximum number of results to return in a single response. The server
// may further constrain the maximum number of results returned in a single
// page. If the page_size is <=0, the server will decide the number of results
// to be returned.
PageSize int32 `protobuf:"varint,3,opt,name=page_size,json=pageSize" json:"page_size,omitempty"`
// If this field is not empty then it must contain the `nextPageToken` value
// returned by a previous call to this method. Using this field causes the
// method to return more results from the previous method call.
PageToken string `protobuf:"bytes,4,opt,name=page_token,json=pageToken" json:"page_token,omitempty"`
}
func (m *ListUptimeCheckConfigsRequest) Reset() { *m = ListUptimeCheckConfigsRequest{} }
func (m *ListUptimeCheckConfigsRequest) String() string { return proto.CompactTextString(m) }
func (*ListUptimeCheckConfigsRequest) ProtoMessage() {}
func (*ListUptimeCheckConfigsRequest) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{0} }
func (m *ListUptimeCheckConfigsRequest) GetParent() string {
if m != nil {
return m.Parent
}
return ""
}
func (m *ListUptimeCheckConfigsRequest) GetPageSize() int32 {
if m != nil {
return m.PageSize
}
return 0
}
func (m *ListUptimeCheckConfigsRequest) GetPageToken() string {
if m != nil {
return m.PageToken
}
return ""
}
// The protocol for the `ListUptimeCheckConfigs` response.
type ListUptimeCheckConfigsResponse struct {
// The returned uptime check configurations.
UptimeCheckConfigs []*UptimeCheckConfig `protobuf:"bytes,1,rep,name=uptime_check_configs,json=uptimeCheckConfigs" json:"uptime_check_configs,omitempty"`
// This field represents the pagination token to retrieve the next page of
// results. If the value is empty, it means no further results for the
// request. To retrieve the next page of results, the value of the
// next_page_token is passed to the subsequent List method call (in the
// request message's page_token field).
NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken" json:"next_page_token,omitempty"`
}
func (m *ListUptimeCheckConfigsResponse) Reset() { *m = ListUptimeCheckConfigsResponse{} }
func (m *ListUptimeCheckConfigsResponse) String() string { return proto.CompactTextString(m) }
func (*ListUptimeCheckConfigsResponse) ProtoMessage() {}
func (*ListUptimeCheckConfigsResponse) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{1} }
func (m *ListUptimeCheckConfigsResponse) GetUptimeCheckConfigs() []*UptimeCheckConfig {
if m != nil {
return m.UptimeCheckConfigs
}
return nil
}
func (m *ListUptimeCheckConfigsResponse) GetNextPageToken() string {
if m != nil {
return m.NextPageToken
}
return ""
}
// The protocol for the `GetUptimeCheckConfig` request.
type GetUptimeCheckConfigRequest struct {
// The uptime check configuration to retrieve. The format is
//
// `projects/[PROJECT_ID]/uptimeCheckConfigs/[UPTIME_CHECK_ID]`.
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
}
func (m *GetUptimeCheckConfigRequest) Reset() { *m = GetUptimeCheckConfigRequest{} }
func (m *GetUptimeCheckConfigRequest) String() string { return proto.CompactTextString(m) }
func (*GetUptimeCheckConfigRequest) ProtoMessage() {}
func (*GetUptimeCheckConfigRequest) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{2} }
func (m *GetUptimeCheckConfigRequest) GetName() string {
if m != nil {
return m.Name
}
return ""
}
// The protocol for the `CreateUptimeCheckConfig` request.
type CreateUptimeCheckConfigRequest struct {
// The project in which to create the uptime check. The format is:
//
// `projects/[PROJECT_ID]`.
Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"`
// The new uptime check configuration.
UptimeCheckConfig *UptimeCheckConfig `protobuf:"bytes,2,opt,name=uptime_check_config,json=uptimeCheckConfig" json:"uptime_check_config,omitempty"`
}
func (m *CreateUptimeCheckConfigRequest) Reset() { *m = CreateUptimeCheckConfigRequest{} }
func (m *CreateUptimeCheckConfigRequest) String() string { return proto.CompactTextString(m) }
func (*CreateUptimeCheckConfigRequest) ProtoMessage() {}
func (*CreateUptimeCheckConfigRequest) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{3} }
func (m *CreateUptimeCheckConfigRequest) GetParent() string {
if m != nil {
return m.Parent
}
return ""
}
func (m *CreateUptimeCheckConfigRequest) GetUptimeCheckConfig() *UptimeCheckConfig {
if m != nil {
return m.UptimeCheckConfig
}
return nil
}
// The protocol for the `UpdateUptimeCheckConfig` request.
type UpdateUptimeCheckConfigRequest struct {
// Optional. If present, only the listed fields in the current uptime check
// configuration are updated with values from the new configuration. If this
// field is empty, then the current configuration is completely replaced with
// the new configuration.
UpdateMask *google_protobuf5.FieldMask `protobuf:"bytes,2,opt,name=update_mask,json=updateMask" json:"update_mask,omitempty"`
// Required. If an `"updateMask"` has been specified, this field gives
// the values for the set of fields mentioned in the `"updateMask"`. If an
// `"updateMask"` has not been given, this uptime check configuration replaces
// the current configuration. If a field is mentioned in `"updateMask`" but
// the corresonding field is omitted in this partial uptime check
// configuration, it has the effect of deleting/clearing the field from the
// configuration on the server.
UptimeCheckConfig *UptimeCheckConfig `protobuf:"bytes,3,opt,name=uptime_check_config,json=uptimeCheckConfig" json:"uptime_check_config,omitempty"`
}
func (m *UpdateUptimeCheckConfigRequest) Reset() { *m = UpdateUptimeCheckConfigRequest{} }
func (m *UpdateUptimeCheckConfigRequest) String() string { return proto.CompactTextString(m) }
func (*UpdateUptimeCheckConfigRequest) ProtoMessage() {}
func (*UpdateUptimeCheckConfigRequest) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{4} }
func (m *UpdateUptimeCheckConfigRequest) GetUpdateMask() *google_protobuf5.FieldMask {
if m != nil {
return m.UpdateMask
}
return nil
}
func (m *UpdateUptimeCheckConfigRequest) GetUptimeCheckConfig() *UptimeCheckConfig {
if m != nil {
return m.UptimeCheckConfig
}
return nil
}
// The protocol for the `DeleteUptimeCheckConfig` request.
type DeleteUptimeCheckConfigRequest struct {
// The uptime check configuration to delete. The format is
//
// `projects/[PROJECT_ID]/uptimeCheckConfigs/[UPTIME_CHECK_ID]`.
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
}
func (m *DeleteUptimeCheckConfigRequest) Reset() { *m = DeleteUptimeCheckConfigRequest{} }
func (m *DeleteUptimeCheckConfigRequest) String() string { return proto.CompactTextString(m) }
func (*DeleteUptimeCheckConfigRequest) ProtoMessage() {}
func (*DeleteUptimeCheckConfigRequest) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{5} }
func (m *DeleteUptimeCheckConfigRequest) GetName() string {
if m != nil {
return m.Name
}
return ""
}
// The protocol for the `ListUptimeCheckIps` request.
type ListUptimeCheckIpsRequest struct {
// The maximum number of results to return in a single response. The server
// may further constrain the maximum number of results returned in a single
// page. If the page_size is <=0, the server will decide the number of results
// to be returned.
// NOTE: this field is not yet implemented
PageSize int32 `protobuf:"varint,2,opt,name=page_size,json=pageSize" json:"page_size,omitempty"`
// If this field is not empty then it must contain the `nextPageToken` value
// returned by a previous call to this method. Using this field causes the
// method to return more results from the previous method call.
// NOTE: this field is not yet implemented
PageToken string `protobuf:"bytes,3,opt,name=page_token,json=pageToken" json:"page_token,omitempty"`
}
func (m *ListUptimeCheckIpsRequest) Reset() { *m = ListUptimeCheckIpsRequest{} }
func (m *ListUptimeCheckIpsRequest) String() string { return proto.CompactTextString(m) }
func (*ListUptimeCheckIpsRequest) ProtoMessage() {}
func (*ListUptimeCheckIpsRequest) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{6} }
func (m *ListUptimeCheckIpsRequest) GetPageSize() int32 {
if m != nil {
return m.PageSize
}
return 0
}
func (m *ListUptimeCheckIpsRequest) GetPageToken() string {
if m != nil {
return m.PageToken
}
return ""
}
// The protocol for the `ListUptimeCheckIps` response.
type ListUptimeCheckIpsResponse struct {
// The returned list of IP addresses (including region and location) that the
// checkers run from.
UptimeCheckIps []*UptimeCheckIp `protobuf:"bytes,1,rep,name=uptime_check_ips,json=uptimeCheckIps" json:"uptime_check_ips,omitempty"`
// This field represents the pagination token to retrieve the next page of
// results. If the value is empty, it means no further results for the
// request. To retrieve the next page of results, the value of the
// next_page_token is passed to the subsequent List method call (in the
// request message's page_token field).
// NOTE: this field is not yet implemented
NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken" json:"next_page_token,omitempty"`
}
func (m *ListUptimeCheckIpsResponse) Reset() { *m = ListUptimeCheckIpsResponse{} }
func (m *ListUptimeCheckIpsResponse) String() string { return proto.CompactTextString(m) }
func (*ListUptimeCheckIpsResponse) ProtoMessage() {}
func (*ListUptimeCheckIpsResponse) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{7} }
func (m *ListUptimeCheckIpsResponse) GetUptimeCheckIps() []*UptimeCheckIp {
if m != nil {
return m.UptimeCheckIps
}
return nil
}
func (m *ListUptimeCheckIpsResponse) GetNextPageToken() string {
if m != nil {
return m.NextPageToken
}
return ""
}
func init() {
proto.RegisterType((*ListUptimeCheckConfigsRequest)(nil), "google.monitoring.v3.ListUptimeCheckConfigsRequest")
proto.RegisterType((*ListUptimeCheckConfigsResponse)(nil), "google.monitoring.v3.ListUptimeCheckConfigsResponse")
proto.RegisterType((*GetUptimeCheckConfigRequest)(nil), "google.monitoring.v3.GetUptimeCheckConfigRequest")
proto.RegisterType((*CreateUptimeCheckConfigRequest)(nil), "google.monitoring.v3.CreateUptimeCheckConfigRequest")
proto.RegisterType((*UpdateUptimeCheckConfigRequest)(nil), "google.monitoring.v3.UpdateUptimeCheckConfigRequest")
proto.RegisterType((*DeleteUptimeCheckConfigRequest)(nil), "google.monitoring.v3.DeleteUptimeCheckConfigRequest")
proto.RegisterType((*ListUptimeCheckIpsRequest)(nil), "google.monitoring.v3.ListUptimeCheckIpsRequest")
proto.RegisterType((*ListUptimeCheckIpsResponse)(nil), "google.monitoring.v3.ListUptimeCheckIpsResponse")
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4
// Client API for UptimeCheckService service
type UptimeCheckServiceClient interface {
// Lists the existing valid uptime check configurations for the project,
// leaving out any invalid configurations.
ListUptimeCheckConfigs(ctx context.Context, in *ListUptimeCheckConfigsRequest, opts ...grpc.CallOption) (*ListUptimeCheckConfigsResponse, error)
// Gets a single uptime check configuration.
GetUptimeCheckConfig(ctx context.Context, in *GetUptimeCheckConfigRequest, opts ...grpc.CallOption) (*UptimeCheckConfig, error)
// Creates a new uptime check configuration.
CreateUptimeCheckConfig(ctx context.Context, in *CreateUptimeCheckConfigRequest, opts ...grpc.CallOption) (*UptimeCheckConfig, error)
// Updates an uptime check configuration. You can either replace the entire
// configuration with a new one or replace only certain fields in the current
// configuration by specifying the fields to be updated via `"updateMask"`.
// Returns the updated configuration.
UpdateUptimeCheckConfig(ctx context.Context, in *UpdateUptimeCheckConfigRequest, opts ...grpc.CallOption) (*UptimeCheckConfig, error)
// Deletes an uptime check configuration. Note that this method will fail
// if the uptime check configuration is referenced by an alert policy or
// other dependent configs that would be rendered invalid by the deletion.
DeleteUptimeCheckConfig(ctx context.Context, in *DeleteUptimeCheckConfigRequest, opts ...grpc.CallOption) (*google_protobuf4.Empty, error)
// Returns the list of IPs that checkers run from
ListUptimeCheckIps(ctx context.Context, in *ListUptimeCheckIpsRequest, opts ...grpc.CallOption) (*ListUptimeCheckIpsResponse, error)
}
type uptimeCheckServiceClient struct {
cc *grpc.ClientConn
}
func NewUptimeCheckServiceClient(cc *grpc.ClientConn) UptimeCheckServiceClient {
return &uptimeCheckServiceClient{cc}
}
func (c *uptimeCheckServiceClient) ListUptimeCheckConfigs(ctx context.Context, in *ListUptimeCheckConfigsRequest, opts ...grpc.CallOption) (*ListUptimeCheckConfigsResponse, error) {
out := new(ListUptimeCheckConfigsResponse)
err := grpc.Invoke(ctx, "/google.monitoring.v3.UptimeCheckService/ListUptimeCheckConfigs", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *uptimeCheckServiceClient) GetUptimeCheckConfig(ctx context.Context, in *GetUptimeCheckConfigRequest, opts ...grpc.CallOption) (*UptimeCheckConfig, error) {
out := new(UptimeCheckConfig)
err := grpc.Invoke(ctx, "/google.monitoring.v3.UptimeCheckService/GetUptimeCheckConfig", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *uptimeCheckServiceClient) CreateUptimeCheckConfig(ctx context.Context, in *CreateUptimeCheckConfigRequest, opts ...grpc.CallOption) (*UptimeCheckConfig, error) {
out := new(UptimeCheckConfig)
err := grpc.Invoke(ctx, "/google.monitoring.v3.UptimeCheckService/CreateUptimeCheckConfig", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *uptimeCheckServiceClient) UpdateUptimeCheckConfig(ctx context.Context, in *UpdateUptimeCheckConfigRequest, opts ...grpc.CallOption) (*UptimeCheckConfig, error) {
out := new(UptimeCheckConfig)
err := grpc.Invoke(ctx, "/google.monitoring.v3.UptimeCheckService/UpdateUptimeCheckConfig", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *uptimeCheckServiceClient) DeleteUptimeCheckConfig(ctx context.Context, in *DeleteUptimeCheckConfigRequest, opts ...grpc.CallOption) (*google_protobuf4.Empty, error) {
out := new(google_protobuf4.Empty)
err := grpc.Invoke(ctx, "/google.monitoring.v3.UptimeCheckService/DeleteUptimeCheckConfig", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *uptimeCheckServiceClient) ListUptimeCheckIps(ctx context.Context, in *ListUptimeCheckIpsRequest, opts ...grpc.CallOption) (*ListUptimeCheckIpsResponse, error) {
out := new(ListUptimeCheckIpsResponse)
err := grpc.Invoke(ctx, "/google.monitoring.v3.UptimeCheckService/ListUptimeCheckIps", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// Server API for UptimeCheckService service
type UptimeCheckServiceServer interface {
// Lists the existing valid uptime check configurations for the project,
// leaving out any invalid configurations.
ListUptimeCheckConfigs(context.Context, *ListUptimeCheckConfigsRequest) (*ListUptimeCheckConfigsResponse, error)
// Gets a single uptime check configuration.
GetUptimeCheckConfig(context.Context, *GetUptimeCheckConfigRequest) (*UptimeCheckConfig, error)
// Creates a new uptime check configuration.
CreateUptimeCheckConfig(context.Context, *CreateUptimeCheckConfigRequest) (*UptimeCheckConfig, error)
// Updates an uptime check configuration. You can either replace the entire
// configuration with a new one or replace only certain fields in the current
// configuration by specifying the fields to be updated via `"updateMask"`.
// Returns the updated configuration.
UpdateUptimeCheckConfig(context.Context, *UpdateUptimeCheckConfigRequest) (*UptimeCheckConfig, error)
// Deletes an uptime check configuration. Note that this method will fail
// if the uptime check configuration is referenced by an alert policy or
// other dependent configs that would be rendered invalid by the deletion.
DeleteUptimeCheckConfig(context.Context, *DeleteUptimeCheckConfigRequest) (*google_protobuf4.Empty, error)
// Returns the list of IPs that checkers run from
ListUptimeCheckIps(context.Context, *ListUptimeCheckIpsRequest) (*ListUptimeCheckIpsResponse, error)
}
func RegisterUptimeCheckServiceServer(s *grpc.Server, srv UptimeCheckServiceServer) {
s.RegisterService(&_UptimeCheckService_serviceDesc, srv)
}
func _UptimeCheckService_ListUptimeCheckConfigs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListUptimeCheckConfigsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(UptimeCheckServiceServer).ListUptimeCheckConfigs(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/google.monitoring.v3.UptimeCheckService/ListUptimeCheckConfigs",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(UptimeCheckServiceServer).ListUptimeCheckConfigs(ctx, req.(*ListUptimeCheckConfigsRequest))
}
return interceptor(ctx, in, info, handler)
}
func _UptimeCheckService_GetUptimeCheckConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetUptimeCheckConfigRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(UptimeCheckServiceServer).GetUptimeCheckConfig(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/google.monitoring.v3.UptimeCheckService/GetUptimeCheckConfig",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(UptimeCheckServiceServer).GetUptimeCheckConfig(ctx, req.(*GetUptimeCheckConfigRequest))
}
return interceptor(ctx, in, info, handler)
}
func _UptimeCheckService_CreateUptimeCheckConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CreateUptimeCheckConfigRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(UptimeCheckServiceServer).CreateUptimeCheckConfig(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/google.monitoring.v3.UptimeCheckService/CreateUptimeCheckConfig",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(UptimeCheckServiceServer).CreateUptimeCheckConfig(ctx, req.(*CreateUptimeCheckConfigRequest))
}
return interceptor(ctx, in, info, handler)
}
func _UptimeCheckService_UpdateUptimeCheckConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(UpdateUptimeCheckConfigRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(UptimeCheckServiceServer).UpdateUptimeCheckConfig(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/google.monitoring.v3.UptimeCheckService/UpdateUptimeCheckConfig",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(UptimeCheckServiceServer).UpdateUptimeCheckConfig(ctx, req.(*UpdateUptimeCheckConfigRequest))
}
return interceptor(ctx, in, info, handler)
}
func _UptimeCheckService_DeleteUptimeCheckConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeleteUptimeCheckConfigRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(UptimeCheckServiceServer).DeleteUptimeCheckConfig(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/google.monitoring.v3.UptimeCheckService/DeleteUptimeCheckConfig",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(UptimeCheckServiceServer).DeleteUptimeCheckConfig(ctx, req.(*DeleteUptimeCheckConfigRequest))
}
return interceptor(ctx, in, info, handler)
}
func _UptimeCheckService_ListUptimeCheckIps_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListUptimeCheckIpsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(UptimeCheckServiceServer).ListUptimeCheckIps(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/google.monitoring.v3.UptimeCheckService/ListUptimeCheckIps",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(UptimeCheckServiceServer).ListUptimeCheckIps(ctx, req.(*ListUptimeCheckIpsRequest))
}
return interceptor(ctx, in, info, handler)
}
var _UptimeCheckService_serviceDesc = grpc.ServiceDesc{
ServiceName: "google.monitoring.v3.UptimeCheckService",
HandlerType: (*UptimeCheckServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "ListUptimeCheckConfigs",
Handler: _UptimeCheckService_ListUptimeCheckConfigs_Handler,
},
{
MethodName: "GetUptimeCheckConfig",
Handler: _UptimeCheckService_GetUptimeCheckConfig_Handler,
},
{
MethodName: "CreateUptimeCheckConfig",
Handler: _UptimeCheckService_CreateUptimeCheckConfig_Handler,
},
{
MethodName: "UpdateUptimeCheckConfig",
Handler: _UptimeCheckService_UpdateUptimeCheckConfig_Handler,
},
{
MethodName: "DeleteUptimeCheckConfig",
Handler: _UptimeCheckService_DeleteUptimeCheckConfig_Handler,
},
{
MethodName: "ListUptimeCheckIps",
Handler: _UptimeCheckService_ListUptimeCheckIps_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "google/monitoring/v3/uptime_service.proto",
}
func init() { proto.RegisterFile("google/monitoring/v3/uptime_service.proto", fileDescriptor6) }
var fileDescriptor6 = []byte{
// 735 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0xdf, 0x4e, 0x13, 0x4f,
0x14, 0xce, 0xb4, 0xfc, 0x08, 0x1c, 0xf2, 0xf3, 0xcf, 0xd8, 0x40, 0x5d, 0xa4, 0xa9, 0x35, 0x51,
0x6c, 0xcc, 0xae, 0xb4, 0x5c, 0x49, 0x24, 0x91, 0xaa, 0x84, 0x44, 0x12, 0x52, 0x04, 0xa2, 0x92,
0x34, 0x4b, 0x19, 0xd6, 0xb5, 0xed, 0xce, 0xd8, 0x99, 0x25, 0x8a, 0xe1, 0xc6, 0x37, 0x30, 0x5c,
0x7a, 0x69, 0xe2, 0x05, 0x0f, 0xa0, 0xd7, 0x5e, 0x99, 0x78, 0x6b, 0x7c, 0x03, 0x1f, 0xc4, 0xec,
0xec, 0x2c, 0xa5, 0xed, 0xec, 0xba, 0x8d, 0x77, 0xdd, 0x39, 0x67, 0xce, 0xf9, 0xce, 0xb7, 0xdf,
0xf9, 0xba, 0x70, 0xdb, 0xa1, 0xd4, 0x69, 0x13, 0xab, 0x43, 0x3d, 0x57, 0xd0, 0xae, 0xeb, 0x39,
0xd6, 0x61, 0xd5, 0xf2, 0x99, 0x70, 0x3b, 0xa4, 0xc1, 0x49, 0xf7, 0xd0, 0x6d, 0x12, 0x93, 0x75,
0xa9, 0xa0, 0x38, 0x17, 0xa6, 0x9a, 0xbd, 0x54, 0xf3, 0xb0, 0x6a, 0x5c, 0x53, 0x05, 0x6c, 0xe6,
0x5a, 0xb6, 0xe7, 0x51, 0x61, 0x0b, 0x97, 0x7a, 0x3c, 0xbc, 0x63, 0x5c, 0x4f, 0x28, 0xaf, 0x52,
0x66, 0x55, 0x8a, 0x7c, 0xda, 0xf3, 0x0f, 0x2c, 0xd2, 0x61, 0xe2, 0xad, 0x0a, 0x16, 0x07, 0x83,
0x07, 0x2e, 0x69, 0xef, 0x37, 0x3a, 0x36, 0x6f, 0x85, 0x19, 0x25, 0x0e, 0x73, 0x4f, 0x5c, 0x2e,
0xb6, 0x64, 0xc9, 0xda, 0x4b, 0xd2, 0x6c, 0xd5, 0xa8, 0x77, 0xe0, 0x3a, 0xbc, 0x4e, 0x5e, 0xfb,
0x84, 0x0b, 0x3c, 0x0d, 0xe3, 0xcc, 0xee, 0x12, 0x4f, 0xe4, 0x51, 0x11, 0xcd, 0x4f, 0xd6, 0xd5,
0x13, 0x9e, 0x85, 0x49, 0x66, 0x3b, 0xa4, 0xc1, 0xdd, 0x23, 0x92, 0xcf, 0x16, 0xd1, 0xfc, 0x7f,
0xf5, 0x89, 0xe0, 0x60, 0xd3, 0x3d, 0x22, 0x78, 0x0e, 0x40, 0x06, 0x05, 0x6d, 0x11, 0x2f, 0x3f,
0x26, 0x2f, 0xca, 0xf4, 0xa7, 0xc1, 0x41, 0xe9, 0x13, 0x82, 0x42, 0x5c, 0x57, 0xce, 0xa8, 0xc7,
0x09, 0x7e, 0x06, 0x39, 0xc5, 0x62, 0x33, 0x08, 0x37, 0x9a, 0x61, 0x3c, 0x8f, 0x8a, 0xd9, 0xf9,
0xa9, 0xca, 0x2d, 0x53, 0x47, 0xa6, 0x39, 0x54, 0xaf, 0x8e, 0xfd, 0xa1, 0x16, 0xf8, 0x26, 0x5c,
0xf4, 0xc8, 0x1b, 0xd1, 0x38, 0x87, 0x30, 0x23, 0x11, 0xfe, 0x1f, 0x1c, 0x6f, 0x9c, 0xa1, 0x5c,
0x80, 0xd9, 0x55, 0x32, 0x8c, 0x31, 0x22, 0x06, 0xc3, 0x98, 0x67, 0x77, 0x88, 0xa2, 0x45, 0xfe,
0x2e, 0x7d, 0x40, 0x50, 0xa8, 0x75, 0x89, 0x2d, 0x48, 0xec, 0xb5, 0x38, 0x3e, 0x77, 0xe0, 0x8a,
0x66, 0x60, 0x89, 0x6c, 0x84, 0x79, 0x2f, 0x0f, 0xcd, 0x5b, 0xfa, 0x82, 0xa0, 0xb0, 0xc5, 0xf6,
0x93, 0x30, 0x2d, 0xc1, 0x94, 0x2f, 0x33, 0xa4, 0x32, 0x54, 0x4f, 0x23, 0xea, 0x19, 0x89, 0xc7,
0x7c, 0x1c, 0x88, 0x67, 0xdd, 0xe6, 0xad, 0x3a, 0x84, 0xe9, 0xc1, 0xef, 0x38, 0xe0, 0xd9, 0x7f,
0x06, 0xbe, 0x08, 0x85, 0x87, 0xa4, 0x4d, 0x12, 0x70, 0xeb, 0x5e, 0xc1, 0x0e, 0x5c, 0x1d, 0x90,
0xd6, 0x1a, 0x3b, 0x13, 0x73, 0x9f, 0x68, 0x33, 0x89, 0xa2, 0xcd, 0x0e, 0x8a, 0xf6, 0x04, 0x81,
0xa1, 0xab, 0xac, 0x04, 0xbb, 0x0e, 0x97, 0xfa, 0x68, 0x70, 0x59, 0x24, 0xd6, 0x1b, 0x7f, 0xe5,
0x60, 0x8d, 0xd5, 0x2f, 0xf8, 0x7d, 0x65, 0xd3, 0x8a, 0xb4, 0xf2, 0x7d, 0x02, 0xf0, 0xb9, 0x4a,
0x9b, 0xa1, 0xe5, 0xe0, 0xaf, 0x08, 0xa6, 0xf5, 0x1b, 0x86, 0xab, 0x7a, 0x38, 0x89, 0x2e, 0x60,
0x2c, 0x8e, 0x76, 0x29, 0xe4, 0xa4, 0x54, 0x79, 0xff, 0xf3, 0xf7, 0x49, 0xe6, 0x0e, 0x2e, 0x07,
0xae, 0xf5, 0x2e, 0x14, 0xfa, 0x7d, 0xd6, 0xa5, 0xaf, 0x48, 0x53, 0x70, 0xab, 0x7c, 0x6c, 0x69,
0xb6, 0xf3, 0x33, 0x82, 0x9c, 0x6e, 0xed, 0xf0, 0x82, 0x1e, 0x42, 0xc2, 0x8a, 0x1a, 0x69, 0xd5,
0x37, 0x00, 0x34, 0xd0, 0xd1, 0x39, 0x98, 0x1a, 0x94, 0x56, 0xf9, 0x18, 0x7f, 0x43, 0x30, 0x13,
0xb3, 0xeb, 0x38, 0x86, 0xae, 0x64, 0x6b, 0x48, 0x0f, 0x77, 0x55, 0xc2, 0x7d, 0x50, 0x1a, 0x81,
0xd7, 0x7b, 0xba, 0x25, 0xc5, 0xbf, 0x10, 0xcc, 0xc4, 0x78, 0x43, 0xdc, 0x0c, 0xc9, 0x56, 0x92,
0x7e, 0x86, 0x17, 0x72, 0x86, 0xad, 0xca, 0xb2, 0x9c, 0x41, 0x03, 0xce, 0x4c, 0xf5, 0x1a, 0xf4,
0x73, 0x7d, 0x44, 0x30, 0x13, 0xe3, 0x1d, 0x71, 0x73, 0x25, 0x5b, 0x8d, 0x31, 0x3d, 0xe4, 0x86,
0x8f, 0x82, 0xff, 0xd9, 0x48, 0x39, 0xe5, 0x51, 0x94, 0x73, 0x82, 0x00, 0x0f, 0x3b, 0x09, 0xb6,
0x52, 0xed, 0x58, 0xcf, 0xcd, 0x8c, 0xbb, 0xe9, 0x2f, 0xa8, 0x85, 0x34, 0x24, 0xda, 0x1c, 0xc6,
0xbd, 0xcf, 0x88, 0x28, 0x67, 0xe5, 0x14, 0x41, 0xbe, 0x49, 0x3b, 0xda, 0x9a, 0x2b, 0xca, 0x63,
0x94, 0xbd, 0x6c, 0x04, 0x1c, 0x6c, 0xa0, 0xe7, 0xcb, 0x2a, 0xd7, 0xa1, 0x6d, 0xdb, 0x73, 0x4c,
0xda, 0x75, 0x2c, 0x87, 0x78, 0x92, 0x21, 0x2b, 0x0c, 0xd9, 0xcc, 0xe5, 0xfd, 0x5f, 0x2f, 0x4b,
0xbd, 0xa7, 0xd3, 0x8c, 0xb1, 0x1a, 0x16, 0xa8, 0xb5, 0xa9, 0xbf, 0x6f, 0xae, 0xf7, 0x5a, 0x6e,
0x57, 0x7f, 0x44, 0xc1, 0x5d, 0x19, 0xdc, 0xed, 0x05, 0x77, 0xb7, 0xab, 0x7b, 0xe3, 0xb2, 0x49,
0xf5, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x4a, 0x1d, 0x15, 0x69, 0x80, 0x09, 0x00, 0x00,
}

View File

@ -228,12 +228,6 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
//
// Note that oneof type names ("test_oneof" in this case) cannot be used in
// paths.
//
// ## Field Mask Verification
//
// The implementation of the all the API methods, which have any FieldMask type
// field in the request, should verify the included field paths, and return
// `INVALID_ARGUMENT` error if any path is duplicated or unmappable.
type FieldMask struct {
// The set of field mask paths.
Paths []string `protobuf:"bytes,1,rep,name=paths" json:"paths,omitempty"`

View File

@ -222,7 +222,7 @@ Args:
<ip> IP address to ping.
[<count>] Number of packets to send
$ ping 1.2.3.4 5
Would ping: 1.2.3.4 with timeout 5s and count 0
Would ping: 1.2.3.4 with timeout 5s and count 5
```
From the following source:
@ -461,7 +461,7 @@ Here are some examples of flags with various permutations:
--name=NAME // Flag(...).String()
--name="Harry" // Flag(...).Default("Harry").String()
--name=FULL-NAME // flag(...).PlaceHolder("FULL-NAME").Default("Harry").String()
--name=FULL-NAME // Flag(...).PlaceHolder("FULL-NAME").Default("Harry").String()
### Consuming all remaining arguments

View File

@ -4,7 +4,7 @@ import (
"fmt"
"os"
"github.com/alecthomas/kingpin"
"gopkg.in/alecthomas/kingpin.v2"
)
func listHosts() []string {

View File

@ -402,6 +402,9 @@ func (a *Application) setDefaults(context *ParseContext) error {
flagElements := map[string]*ParseElement{}
for _, element := range context.Elements {
if flag, ok := element.Clause.(*FlagClause); ok {
if flag.name == "help" {
return nil
}
flagElements[flag.name] = element
}
}

View File

@ -3,7 +3,7 @@ package kingpin
import (
"io/ioutil"
"github.com/alecthomas/assert"
"github.com/stretchr/testify/assert"
"sort"
"strings"

View File

@ -5,7 +5,7 @@ import (
"os"
"testing"
"github.com/alecthomas/assert"
"github.com/stretchr/testify/assert"
)
func TestArgRemainder(t *testing.T) {

View File

@ -4,7 +4,7 @@ import (
"sort"
"strings"
"github.com/alecthomas/assert"
"github.com/stretchr/testify/assert"
"testing"
)

View File

@ -3,7 +3,7 @@ package kingpin
import (
"testing"
"github.com/alecthomas/assert"
"github.com/stretchr/testify/assert"
)
func TestResolveWithBuiltin(t *testing.T) {

View File

@ -4,7 +4,7 @@ import (
"io/ioutil"
"os"
"github.com/alecthomas/assert"
"github.com/stretchr/testify/assert"
"testing"
)

View File

@ -153,6 +153,10 @@ func (p *ParseContext) EOL() bool {
return p.Peek().Type == TokenEOL
}
func (p *ParseContext) Error() bool {
return p.Peek().Type == TokenError
}
// Next token in the parse context.
func (p *ParseContext) Next() *Token {
if len(p.peek) > 0 {
@ -266,9 +270,12 @@ func (p *ParseContext) matchedCmd(cmd *CmdClause) {
// Expand arguments from a file. Lines starting with # will be treated as comments.
func ExpandArgsFromFile(filename string) (out []string, err error) {
if filename == "" {
return nil, fmt.Errorf("expected @ file to expand arguments from")
}
r, err := os.Open(filename)
if err != nil {
return nil, err
return nil, fmt.Errorf("failed to open arguments file %q: %s", filename, err)
}
defer r.Close()
scanner := bufio.NewScanner(r)
@ -280,6 +287,9 @@ func ExpandArgsFromFile(filename string) (out []string, err error) {
out = append(out, line)
}
err = scanner.Err()
if err != nil {
return nil, fmt.Errorf("failed to read arguments from %q: %s", filename, err)
}
return
}
@ -291,7 +301,7 @@ func parse(context *ParseContext, app *Application) (err error) {
ignoreDefault := context.ignoreDefault
loop:
for !context.EOL() {
for !context.EOL() && !context.Error() {
token := context.Peek()
switch token.Type {
@ -365,6 +375,10 @@ loop:
}
}
if context.Error() {
return fmt.Errorf("%s", context.Peek().Value)
}
if !context.EOL() {
return fmt.Errorf("unexpected %s", context.Peek())
}

View File

@ -5,7 +5,7 @@ import (
"os"
"testing"
"github.com/alecthomas/assert"
"github.com/stretchr/testify/assert"
)
func TestParserExpandFromFile(t *testing.T) {

View File

@ -6,7 +6,7 @@ import (
"net/url"
"os"
"github.com/alecthomas/assert"
"github.com/stretchr/testify/assert"
"testing"
)

View File

@ -5,7 +5,7 @@ import (
"strings"
"testing"
"github.com/alecthomas/assert"
"github.com/stretchr/testify/assert"
)
func TestFormatTwoColumns(t *testing.T) {

View File

@ -3,7 +3,7 @@ package kingpin
import (
"net"
"github.com/alecthomas/assert"
"github.com/stretchr/testify/assert"
"testing"
)