Merge pull request #126 from glower/hipchat-approve-bot
move slack related bot code to a sub modulepull/128/head
commit
9a8f8090c4
348
bot/bot.go
348
bot/bot.go
|
@ -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 + "```"
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
|
@ -1,4 +1,4 @@
|
|||
package bot
|
||||
package slack
|
||||
|
||||
import (
|
||||
"bytes"
|
|
@ -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 + "```"
|
||||
}
|
|
@ -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)
|
|
@ -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()) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
14
glide.yaml
14
glide.yaml
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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.
|
|
@ -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
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 {}
|
||||
}
|
|
@ -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 {}
|
||||
}
|
|
@ -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")
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
@ -1 +0,0 @@
|
|||
hipfile
|
|
@ -1 +0,0 @@
|
|||
hiptail
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
||||
}
|
|
@ -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) })
|
||||
}
|
|
@ -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])
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
1196
vendor/google.golang.org/genproto/googleapis/assistant/embedded/v1alpha2/embedded_assistant.pb.go
generated
vendored
Normal file
1196
vendor/google.golang.org/genproto/googleapis/assistant/embedded/v1alpha2/embedded_assistant.pb.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
660
vendor/google.golang.org/genproto/googleapis/cloud/dataproc/v1/clusters.pb.go
generated
vendored
660
vendor/google.golang.org/genproto/googleapis/cloud/dataproc/v1/clusters.pb.go
generated
vendored
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
105
vendor/google.golang.org/genproto/googleapis/cloud/dataproc/v1/operations.pb.go
generated
vendored
105
vendor/google.golang.org/genproto/googleapis/cloud/dataproc/v1/operations.pb.go
generated
vendored
|
@ -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,
|
||||
}
|
||||
|
|
1775
vendor/google.golang.org/genproto/googleapis/cloud/dataproc/v1beta2/clusters.pb.go
generated
vendored
Normal file
1775
vendor/google.golang.org/genproto/googleapis/cloud/dataproc/v1beta2/clusters.pb.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2573
vendor/google.golang.org/genproto/googleapis/cloud/dataproc/v1beta2/jobs.pb.go
generated
vendored
Normal file
2573
vendor/google.golang.org/genproto/googleapis/cloud/dataproc/v1beta2/jobs.pb.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
221
vendor/google.golang.org/genproto/googleapis/cloud/dataproc/v1beta2/operations.pb.go
generated
vendored
Normal file
221
vendor/google.golang.org/genproto/googleapis/cloud/dataproc/v1beta2/operations.pb.go
generated
vendored
Normal 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,
|
||||
}
|
1526
vendor/google.golang.org/genproto/googleapis/cloud/dataproc/v1beta2/workflow_templates.pb.go
generated
vendored
Normal file
1526
vendor/google.golang.org/genproto/googleapis/cloud/dataproc/v1beta2/workflow_templates.pb.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1327
vendor/google.golang.org/genproto/googleapis/cloud/iot/v1/device_manager.pb.go
generated
vendored
Normal file
1327
vendor/google.golang.org/genproto/googleapis/cloud/iot/v1/device_manager.pb.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1026
vendor/google.golang.org/genproto/googleapis/cloud/iot/v1/resources.pb.go
generated
vendored
Normal file
1026
vendor/google.golang.org/genproto/googleapis/cloud/iot/v1/resources.pb.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
|
||||
|
|
748
vendor/google.golang.org/genproto/googleapis/monitoring/v3/uptime.pb.go
generated
vendored
Normal file
748
vendor/google.golang.org/genproto/googleapis/monitoring/v3/uptime.pb.go
generated
vendored
Normal 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,
|
||||
}
|
591
vendor/google.golang.org/genproto/googleapis/monitoring/v3/uptime_service.pb.go
generated
vendored
Normal file
591
vendor/google.golang.org/genproto/googleapis/monitoring/v3/uptime_service.pb.go
generated
vendored
Normal 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,
|
||||
}
|
|
@ -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"`
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/alecthomas/kingpin"
|
||||
"gopkg.in/alecthomas/kingpin.v2"
|
||||
)
|
||||
|
||||
func listHosts() []string {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ package kingpin
|
|||
import (
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/alecthomas/assert"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"sort"
|
||||
"strings"
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/alecthomas/assert"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestArgRemainder(t *testing.T) {
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/alecthomas/assert"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"testing"
|
||||
)
|
||||
|
|
|
@ -3,7 +3,7 @@ package kingpin
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/alecthomas/assert"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestResolveWithBuiltin(t *testing.T) {
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/alecthomas/assert"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"testing"
|
||||
)
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/alecthomas/assert"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestParserExpandFromFile(t *testing.T) {
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
"net/url"
|
||||
"os"
|
||||
|
||||
"github.com/alecthomas/assert"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"testing"
|
||||
)
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/alecthomas/assert"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestFormatTwoColumns(t *testing.T) {
|
||||
|
|
|
@ -3,7 +3,7 @@ package kingpin
|
|||
import (
|
||||
"net"
|
||||
|
||||
"github.com/alecthomas/assert"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"testing"
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue