go.fuchsia.dev/infra@v0.0.0-20240507153436-9b593402251b/cmd/autogardener/common.go (about)

     1  // Copyright 2022 The Fuchsia Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style license that can be
     3  // found in the LICENSE file.
     4  
     5  package main
     6  
     7  import (
     8  	"context"
     9  
    10  	"cloud.google.com/go/bigquery"
    11  	"github.com/maruel/subcommands"
    12  	"go.chromium.org/luci/auth"
    13  	"go.chromium.org/luci/auth/client/authcli"
    14  	"golang.org/x/exp/constraints"
    15  	"google.golang.org/api/iterator"
    16  )
    17  
    18  type commonFlags struct {
    19  	subcommands.CommandRunBase
    20  	authFlags authcli.Flags
    21  	project   string
    22  
    23  	parsedAuthOpts auth.Options
    24  }
    25  
    26  func (c *commonFlags) Init(authOpts auth.Options) {
    27  	c.authFlags = authcli.Flags{}
    28  	c.authFlags.Register(&c.Flags, authOpts)
    29  }
    30  
    31  func (c *commonFlags) Parse() error {
    32  	var err error
    33  	c.parsedAuthOpts, err = c.authFlags.Options()
    34  	if err != nil {
    35  		return err
    36  	}
    37  	return nil
    38  }
    39  
    40  func runQuery[T any](ctx context.Context, client *bigquery.Client, query string, params map[string]any) ([]T, error) {
    41  	q := client.Query(query)
    42  	for k, v := range params {
    43  		q.Parameters = append(q.Parameters, bigquery.QueryParameter{Name: k, Value: v})
    44  	}
    45  	iter, err := q.Read(ctx)
    46  	if err != nil {
    47  		return nil, err
    48  	}
    49  
    50  	var rows []T
    51  	for {
    52  		var row T
    53  		err := iter.Next(&row)
    54  		if err == iterator.Done {
    55  			break
    56  		} else if err != nil {
    57  			return nil, err
    58  		}
    59  		rows = append(rows, row)
    60  	}
    61  
    62  	return rows, nil
    63  }
    64  
    65  func average[T constraints.Float | constraints.Integer](nums []T) float64 {
    66  	if len(nums) == 0 {
    67  		panic("average of empty slice")
    68  	}
    69  	var sum T
    70  	for _, num := range nums {
    71  		sum += num
    72  	}
    73  	return float64(sum) / float64(len(nums))
    74  }