func NewClient(ctx context.Context, binauthProject string, keyring signer.AttestationSigner) (*Client, error) {
	var err error
	caClient, err := containeranalysisapi.NewClient(ctx)
	if err != nil {
		return nil, err
	}
	client := &Client{
		containeranalysis: caClient.GetGrafeasClient(),
		keyring:           keyring,
		binauthProject:    binauthProject,
	}
	return client, nil
}
NewClient creates a new containeranalysis Grafeas Client.
package containeranalysis
import (
	"context"
	"errors"
	containeranalysisapi "cloud.google.com/go/containeranalysis/apiv1"
	grafeasv1 "cloud.google.com/go/grafeas/apiv1"
	"github.com/docker/distribution/reference"
	"google.golang.org/api/iterator"
	grafeas "google.golang.org/genproto/googleapis/grafeas/v1"
	voucher "github.com/grafeas/voucher/v2"
	"github.com/grafeas/voucher/v2/attestation"
	"github.com/grafeas/voucher/v2/docker/uri"
	"github.com/grafeas/voucher/v2/repository"
	"github.com/grafeas/voucher/v2/signer"
)
var errCannotAttest = errors.New("cannot create attestations, keyring is empty")
type Client struct {
	containeranalysis *grafeasv1.Client         
	keyring           signer.AttestationSigner  
	binauthProject    string                    
}
func (g *Client) CanAttest() bool {
	return nil != g.keyring
}
func (g *Client) NewPayloadBody(ref reference.Canonical) (string, error) {
	payload, err := attestation.NewPayload(ref).ToString()
	if err != nil {
		return "", err
	}
	return payload, err
}
func (g *Client) AddAttestationToImage(ctx context.Context, ref reference.Canonical, attestation voucher.Attestation) (voucher.SignedAttestation, error) {
	if !g.CanAttest() {
		return voucher.SignedAttestation{}, errCannotAttest
	}
	signedAttestation, err := voucher.SignAttestation(g.keyring, attestation)
	if nil != err {
		return voucher.SignedAttestation{}, err
	}
	_, err = g.containeranalysis.CreateOccurrence(
		ctx,
		newOccurrenceAttestation(
			ref,
			signedAttestation,
			g.binauthProject,
		),
	)
	if isAttestionExistsErr(err) {
		err = nil
		signedAttestation.Signature = ""
	}
	return signedAttestation, err
}
func (g *Client) GetAttestations(ctx context.Context, ref reference.Canonical) ([]voucher.SignedAttestation, error) {
	filterStr := kindFilterStr(ref, grafeas.NoteKind_ATTESTATION)
	var attestations []voucher.SignedAttestation
	project := projectPath(g.binauthProject)
	req := &grafeas.ListOccurrencesRequest{Parent: project, Filter: filterStr}
	occIterator := g.containeranalysis.ListOccurrences(ctx, req)
	for {
		occ, err := occIterator.Next()
		if nil != err {
			if iterator.Done == err {
				return attestations, nil
			}
			return nil, err
		}
		note, err := g.containeranalysis.GetOccurrenceNote(
			ctx,
			&grafeas.GetOccurrenceNoteRequest{
				Name: occ.GetName(),
			},
		)
		if nil != err {
			return nil, err
		}
		name := getCheckNameFromNoteName(g.binauthProject, note.GetName())
		attestations = append(
			attestations,
			OccurrenceToAttestation(name, occ),
		)
	}
}
func (g *Client) GetVulnerabilities(ctx context.Context, ref reference.Canonical) (vulnerabilities []voucher.Vulnerability, err error) {
	filterStr := kindFilterStr(ref, grafeas.NoteKind_VULNERABILITY)
	err = pollForDiscoveries(ctx, g, ref)
	if nil != err {
		return []voucher.Vulnerability{}, err
	}
	project, err := uri.ReferenceToProjectName(ref)
	if nil != err {
		return []voucher.Vulnerability{}, err
	}
	req := &grafeas.ListOccurrencesRequest{Parent: projectPath(project), Filter: filterStr}
	occIterator := g.containeranalysis.ListOccurrences(ctx, req)
	for {
		var occ *grafeas.Occurrence
		occ, err = occIterator.Next()
		if nil != err {
			if iterator.Done == err {
				err = nil
			}
			break
		}
		vuln := OccurrenceToVulnerability(occ)
		vulnerabilities = append(vulnerabilities, vuln)
	}
	return
}
func (g *Client) Close() {
	if nil != g.keyring {
		_ = g.keyring.Close()
	}
	g.containeranalysis.Close()
}
func (g *Client) GetBuildDetail(ctx context.Context, ref reference.Canonical) (repository.BuildDetail, error) {
	var err error
	filterStr := kindFilterStr(ref, grafeas.NoteKind_BUILD)
	project, err := uri.ReferenceToProjectName(ref)
	if nil != err {
		return repository.BuildDetail{}, err
	}
	req := &grafeas.ListOccurrencesRequest{Parent: projectPath(project), Filter: filterStr}
	occIterator := g.containeranalysis.ListOccurrences(ctx, req)
	occ, err := occIterator.Next()
	if err != nil {
		if err == iterator.Done {
			err = &voucher.NoMetadataError{
				Type: voucher.VulnerabilityType,
				Err:  errNoOccurrences,
			}
		}
		return repository.BuildDetail{}, err
	}
	if _, err := occIterator.Next(); err != iterator.Done {
		return repository.BuildDetail{}, errors.New("Found multiple Grafeas occurrences for " + ref.String())
	}
	return OccurrenceToBuildDetail(occ), nil
}