github.com/munnerz/test-infra@v0.0.0-20190108210205-ce3d181dc989/prow/pubsub/reporter/reporter.go (about) 1 /* 2 Copyright 2018 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 // Package reporter contains helpers for publishing statues to Pub 18 // statuses in Github. 19 package reporter 20 21 import ( 22 "context" 23 "encoding/json" 24 "fmt" 25 26 "cloud.google.com/go/pubsub" 27 28 "k8s.io/test-infra/prow/kube" 29 ) 30 31 const ( 32 // PubSubProjectLabel annotation 33 PubSubProjectLabel = "prow.k8s.io/pubsub.project" 34 // PubSubTopicLabel annotation 35 PubSubTopicLabel = "prow.k8s.io/pubsub.topic" 36 // PubSubRunIDLabel annotation 37 PubSubRunIDLabel = "prow.k8s.io/pubsub.runID" 38 ) 39 40 // ReportMessage is a message structure used to pass a prowjob status to Pub/Sub topic.s 41 type ReportMessage struct { 42 Project string `json:"project"` 43 Topic string `json:"topic"` 44 RunID string `json:"runid"` 45 Status kube.ProwJobState `json:"status"` 46 URL string `json:"url"` 47 } 48 49 // Client is a reporter client fed to crier controller 50 type Client struct { 51 // Empty structure because unlike github or gerrit client, one GCP Pub/Sub client is tied to one GCP project. 52 // While GCP project name is provided by the label in each prowjob. 53 // Which means we could create a Pub/Sub client only when we actually get a prowjob to do reporting, 54 // instead of creating a Pub/Sub client while initializing the reporter client. 55 } 56 57 // NewReporter creates a new Pub/Sub reporter 58 func NewReporter() *Client { 59 return &Client{} 60 } 61 62 // GetName returns the name of the reporter 63 func (c *Client) GetName() string { 64 return "pubsub-reporter" 65 } 66 67 // ShouldReport tells if a prowjob should be reported by this reporter 68 func (c *Client) ShouldReport(pj *kube.ProwJob) bool { 69 return pj.Labels[PubSubProjectLabel] != "" && pj.Labels[PubSubTopicLabel] != "" 70 } 71 72 // Report takes a prowjob, and generate a pubsub ReportMessage and publish to specific Pub/Sub topic 73 // based on Pub/Sub related labels if they exist in this prowjob 74 func (c *Client) Report(pj *kube.ProwJob) error { 75 message := generateMessageFromPJ(pj) 76 77 ctx := context.Background() 78 client, err := pubsub.NewClient(ctx, message.Project) 79 80 if err != nil { 81 return fmt.Errorf("could not create pubsub Client: %v", err) 82 } 83 topic := client.Topic(message.Topic) 84 85 d, err := json.Marshal(message) 86 if err != nil { 87 return fmt.Errorf("could not marshal pubsub report: %v", err) 88 } 89 90 res := topic.Publish(ctx, &pubsub.Message{ 91 Data: d, 92 }) 93 94 _, err = res.Get(ctx) 95 if err != nil { 96 return fmt.Errorf("failed to publish pubsub message: %v", err) 97 } 98 99 return nil 100 } 101 102 func generateMessageFromPJ(pj *kube.ProwJob) *ReportMessage { 103 projectName := pj.Labels[PubSubProjectLabel] 104 topicName := pj.Labels[PubSubTopicLabel] 105 runID := pj.GetLabels()[PubSubRunIDLabel] 106 107 psReport := &ReportMessage{ 108 Project: projectName, 109 Topic: topicName, 110 RunID: runID, 111 Status: pj.Status.State, 112 URL: pj.Status.URL, 113 } 114 115 return psReport 116 }