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  }