Skip to content

Commit

Permalink
[WIP] Adopt metal-go
Browse files Browse the repository at this point in the history
  • Loading branch information
ctreatma committed Mar 22, 2023
1 parent 74304df commit 3740c6b
Show file tree
Hide file tree
Showing 11 changed files with 170 additions and 144 deletions.
59 changes: 23 additions & 36 deletions cmd/ci-clean/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
"strings"
"time"

"github.com/packethost/packngo"
metal "github.com/equinix-labs/metal-go/metal/v1"
"github.com/spf13/cobra"
kerrors "k8s.io/apimachinery/pkg/util/errors"

Expand Down Expand Up @@ -66,51 +66,45 @@ func main() {

func cleanup(metalAuthToken, metalProjectID string) error {
metalClient := packet.NewClient(metalAuthToken)
listOpts := &packngo.ListOptions{}
var errs []error

devices, _, err := metalClient.Devices.List(metalProjectID, listOpts)
devices, _, err := metalClient.DevicesApi.FindProjectDevices(nil, metalProjectID).Execute()
if err != nil {
return fmt.Errorf("failed to list devices: %w", err)
}

if err := deleteDevices(metalClient, devices); err != nil {
if err := deleteDevices(metalClient, *devices); err != nil {
errs = append(errs, err)
}

ips, _, err := metalClient.ProjectIPs.List(metalProjectID, listOpts)
ips, _, err := metalClient.IPAddressesApi.FindIPReservations(nil, metalProjectID).Execute()
if err != nil {
return fmt.Errorf("failed to list ip addresses: %w", err)
}

if err := deleteIPs(metalClient, ips); err != nil {
if err := deleteIPs(metalClient, *ips); err != nil {
errs = append(errs, err)
}

keys, _, err := metalClient.Projects.ListSSHKeys(metalProjectID, listOpts)
keys, _, err := metalClient.SSHKeysApi.FindProjectSSHKeys(nil, metalProjectID).Execute()
if err != nil {
return fmt.Errorf("failed to list ssh keys: %w", err)
}

if err := deleteKeys(metalClient, keys); err != nil {
if err := deleteKeys(metalClient, *keys); err != nil {
errs = append(errs, err)
}

return kerrors.NewAggregate(errs)
}

func deleteDevices(metalClient *packet.Client, devices []packngo.Device) error {
func deleteDevices(metalClient *packet.Client, devices metal.DeviceList) error {
var errs []error

for _, d := range devices {
created, err := time.Parse(time.RFC3339, d.Created)
if err != nil {
errs = append(errs, fmt.Errorf("failed to parse creation time for device %q: %w", d.Hostname, err))
continue
}
if time.Since(created) > 4*time.Hour {
for _, d := range devices.Devices {
if time.Since(*d.CreatedAt) > 4*time.Hour {
fmt.Printf("Deleting device: %s\n", d.Hostname)
_, err := metalClient.Devices.Delete(d.ID, false)
_, err := metalClient.DevicesApi.DeleteDevice(nil, *d.Id).ForceDelete(false).Execute()
if err != nil {
errs = append(errs, fmt.Errorf("failed to delete device %q: %w", d.Hostname, err))
}
Expand All @@ -120,22 +114,20 @@ func deleteDevices(metalClient *packet.Client, devices []packngo.Device) error {
return kerrors.NewAggregate(errs)
}

func deleteIPs(metalClient *packet.Client, ips []packngo.IPAddressReservation) error {
func deleteIPs(metalClient *packet.Client, ips metal.IPReservationList) error {
var errs []error

for _, ip := range ips {
created, err := time.Parse(time.RFC3339, ip.Created)
if err != nil {
errs = append(errs, fmt.Errorf("failed to parse creation time for ip address %q: %w", ip.Address, err))
continue
}

if time.Since(created) > 4*time.Hour {
for _, reservation := range ips.IpAddresses {
// TODO: per the spec, `reservation` could be an `IPReservation` or a `VrfIpReservation`
// maybe metal-go could define and we could move the if block to function that takes
// that interface as an argument
ip := reservation.IPReservation
if ip != nil && time.Since(*ip.CreatedAt) > 4*time.Hour {
for _, tag := range ip.Tags {
if strings.HasPrefix(tag, "cluster-api-provider-packet:cluster-id:") || strings.HasPrefix(tag, "usage=cloud-provider-equinix-metal-auto") {
fmt.Printf("Deleting IP: %s\n", ip.Address)

if _, err := metalClient.ProjectIPs.Remove(ip.ID); err != nil {
if _, err := metalClient.IPAddressesApi.DeleteIPAddress(nil, *ip.Id).Execute(); err != nil {
errs = append(errs, fmt.Errorf("failed to delete ip address %q: %w", ip.Address, err))
}

Expand All @@ -148,18 +140,13 @@ func deleteIPs(metalClient *packet.Client, ips []packngo.IPAddressReservation) e
return kerrors.NewAggregate(errs)
}

func deleteKeys(metalClient *packet.Client, keys []packngo.SSHKey) error {
func deleteKeys(metalClient *packet.Client, keys metal.SSHKeyList) error {
var errs []error

for _, k := range keys {
created, err := time.Parse(time.RFC3339, k.Created)
if err != nil {
errs = append(errs, fmt.Errorf("failed to parse creation time for SSH Key %q: %w", k.Label, err))
continue
}
if time.Since(created) > 4*time.Hour {
for _, k := range keys.SshKeys {
if time.Since(*k.CreatedAt) > 4*time.Hour {
fmt.Printf("Deleting SSH Key: %s\n", k.Label)
_, err := metalClient.SSHKeys.Delete(k.ID)
_, err := metalClient.SSHKeysApi.DeleteSSHKey(nil, *k.Id).Execute()
if err != nil {
errs = append(errs, fmt.Errorf("failed to delete SSH Key %q: %w", k.Label, err))
}
Expand Down
8 changes: 4 additions & 4 deletions controllers/packetcluster_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,11 @@ func (r *PacketClusterReconciler) reconcileNormal(ctx context.Context, clusterSc

packetCluster := clusterScope.PacketCluster

ipReserv, err := r.PacketClient.GetIPByClusterIdentifier(clusterScope.Namespace(), clusterScope.Name(), packetCluster.Spec.ProjectID)
ipReserv, err := r.PacketClient.GetIPByClusterIdentifier(ctx, clusterScope.Namespace(), clusterScope.Name(), packetCluster.Spec.ProjectID)
switch {
case errors.Is(err, packet.ErrControlPlanEndpointNotFound):
// There is not an ElasticIP with the right tags, at this point we can create one
ip, err := r.PacketClient.CreateIP(clusterScope.Namespace(), clusterScope.Name(), packetCluster.Spec.ProjectID, packetCluster.Spec.Facility)
ip, err := r.PacketClient.CreateIP(ctx, clusterScope.Namespace(), clusterScope.Name(), packetCluster.Spec.ProjectID, packetCluster.Spec.Facility)
if err != nil {
log.Error(err, "error reserving an ip")
return ctrl.Result{}, err
Expand All @@ -132,13 +132,13 @@ func (r *PacketClusterReconciler) reconcileNormal(ctx context.Context, clusterSc
default:
// If there is an ElasticIP with the right tag just use it again
clusterScope.PacketCluster.Spec.ControlPlaneEndpoint = clusterv1.APIEndpoint{
Host: ipReserv.Address,
Host: *ipReserv.Address,
Port: 6443,
}
}

if clusterScope.PacketCluster.Spec.VIPManager == "KUBE_VIP" {
if err := r.PacketClient.EnableProjectBGP(packetCluster.Spec.ProjectID); err != nil {
if err := r.PacketClient.EnableProjectBGP(ctx, packetCluster.Spec.ProjectID); err != nil {
log.Error(err, "error enabling bgp for project")
return ctrl.Result{}, err
}
Expand Down
55 changes: 31 additions & 24 deletions controllers/packetmachine_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
"strings"
"time"

"github.com/packethost/packngo"
metal "github.com/equinix-labs/metal-go/metal/v1"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
Expand Down Expand Up @@ -254,26 +254,26 @@ func (r *PacketMachineReconciler) reconcile(ctx context.Context, machineScope *s

providerID := machineScope.GetInstanceID()
var (
dev *packngo.Device
dev *metal.Device
addrs []corev1.NodeAddress
err error
controlPlaneEndpoint packngo.IPAddressReservation
controlPlaneEndpoint *metal.IPReservation
resp *http.Response
)

if providerID != "" {
// If we already have a providerID, then retrieve the device using the
// providerID. This means that the Machine has already been created
// and we successfully recorded the providerID.
dev, err = r.PacketClient.GetDevice(providerID)
dev, resp, err = r.PacketClient.GetDevice(ctx, providerID)
if err != nil {
var perr *packngo.ErrorResponse
if errors.As(err, &perr) && perr.Response != nil {
if perr.Response.StatusCode == http.StatusNotFound {
if resp != nil {
if resp.StatusCode == http.StatusNotFound {
machineScope.SetFailureReason(capierrors.UpdateMachineError)
machineScope.SetFailureMessage(fmt.Errorf("failed to find device: %w", err))
log.Error(err, "unable to find device")
conditions.MarkFalse(machineScope.PacketMachine, infrav1.DeviceReadyCondition, infrav1.InstanceNotFoundReason, clusterv1.ConditionSeverityError, err.Error())
} else if perr.Response.StatusCode == http.StatusForbidden {
} else if resp.StatusCode == http.StatusForbidden {
machineScope.SetFailureReason(capierrors.UpdateMachineError)
log.Error(err, "device failed to provision")
machineScope.SetFailureMessage(fmt.Errorf("device failed to provision: %w", err))
Expand All @@ -290,6 +290,7 @@ func (r *PacketMachineReconciler) reconcile(ctx context.Context, machineScope *s
// created a device by using the tags that we assign to devices
// on creation.
dev, err = r.PacketClient.GetDeviceByTags(
ctx,
machineScope.PacketCluster.Spec.ProjectID,
packet.DefaultCreateTags(machineScope.Namespace(), machineScope.Machine.Name, machineScope.Cluster.Name),
)
Expand Down Expand Up @@ -320,19 +321,20 @@ func (r *PacketMachineReconciler) reconcile(ctx context.Context, machineScope *s
// to template out the kube-vip deployment
if machineScope.IsControlPlane() {
controlPlaneEndpoint, _ = r.PacketClient.GetIPByClusterIdentifier(
ctx,
machineScope.Cluster.Namespace,
machineScope.Cluster.Name,
machineScope.PacketCluster.Spec.ProjectID)
if machineScope.PacketCluster.Spec.VIPManager == "CPEM" {
if len(controlPlaneEndpoint.Assignments) == 0 {
a := corev1.NodeAddress{
Type: corev1.NodeExternalIP,
Address: controlPlaneEndpoint.Address,
Address: *controlPlaneEndpoint.Address,
}
addrs = append(addrs, a)
}
}
createDeviceReq.ControlPlaneEndpoint = controlPlaneEndpoint.Address
createDeviceReq.ControlPlaneEndpoint = *controlPlaneEndpoint.Address
}

dev, err = r.PacketClient.NewDevice(ctx, createDeviceReq)
Expand All @@ -359,11 +361,11 @@ func (r *PacketMachineReconciler) reconcile(ctx context.Context, machineScope *s
}

// we do not need to set this as equinixmetal://<id> because SetProviderID() does the formatting for us
machineScope.SetProviderID(dev.ID)
machineScope.SetInstanceStatus(infrav1.PacketResourceStatus(dev.State))
machineScope.SetProviderID(*dev.Id)
machineScope.SetInstanceStatus(infrav1.PacketResourceStatus(*dev.State))

if machineScope.PacketCluster.Spec.VIPManager == "KUBE_VIP" {
if err := r.PacketClient.EnsureNodeBGPEnabled(dev.ID); err != nil {
if err := r.PacketClient.EnsureNodeBGPEnabled(ctx, *dev.Id); err != nil {
// Do not treat an error enabling bgp on machine as fatal
return ctrl.Result{RequeueAfter: time.Second * 20}, fmt.Errorf("failed to enable bpg on machine %s: %w", machineScope.Name(), err)
}
Expand All @@ -375,7 +377,7 @@ func (r *PacketMachineReconciler) reconcile(ctx context.Context, machineScope *s
// Proceed to reconcile the PacketMachine state.
var result reconcile.Result

switch infrav1.PacketResourceStatus(dev.State) {
switch infrav1.PacketResourceStatus(*dev.State) {
case infrav1.PacketResourceStatusNew, infrav1.PacketResourceStatusQueued, infrav1.PacketResourceStatusProvisioning:
log.Info("Machine instance is pending", "instance-id", machineScope.GetInstanceID())
machineScope.SetNotReady()
Expand All @@ -385,13 +387,16 @@ func (r *PacketMachineReconciler) reconcile(ctx context.Context, machineScope *s

if machineScope.PacketCluster.Spec.VIPManager == "CPEM" {
controlPlaneEndpoint, _ = r.PacketClient.GetIPByClusterIdentifier(
ctx,
machineScope.Cluster.Namespace,
machineScope.Cluster.Name,
machineScope.PacketCluster.Spec.ProjectID)
if len(controlPlaneEndpoint.Assignments) == 0 && machineScope.IsControlPlane() {
if _, _, err := r.PacketClient.DeviceIPs.Assign(dev.ID, &packngo.AddressStruct{
Address: controlPlaneEndpoint.Address,
}); err != nil {
apiRequest := r.PacketClient.DevicesApi.CreateIPAssignment(nil, *dev.Id)
apiRequest.IPAssignmentInput(metal.IPAssignmentInput{
Address: *controlPlaneEndpoint.Address,
})
if _, _, err := apiRequest.Execute(); err != nil {
log.Error(err, "err assigining elastic ip to control plane. retrying...")
return ctrl.Result{RequeueAfter: time.Second * 20}, nil
}
Expand Down Expand Up @@ -422,12 +427,13 @@ func (r *PacketMachineReconciler) reconcileDelete(ctx context.Context, machineSc
packetmachine := machineScope.PacketMachine
providerID := machineScope.GetInstanceID()

var device *packngo.Device
var device *metal.Device

if providerID == "" {
// If no providerID was recorded, check to see if there are any instances
// that match by tags
dev, err := r.PacketClient.GetDeviceByTags(
ctx,
machineScope.PacketCluster.Spec.ProjectID,
packet.DefaultCreateTags(machineScope.Namespace(), machineScope.Machine.Name, machineScope.Cluster.Name),
)
Expand All @@ -443,20 +449,20 @@ func (r *PacketMachineReconciler) reconcileDelete(ctx context.Context, machineSc

device = dev
} else {
var resp *http.Response
// Otherwise, try to retrieve the device by the providerID
dev, err := r.PacketClient.GetDevice(providerID)
dev, resp, err := r.PacketClient.GetDevice(ctx, providerID)
if err != nil {
var errResp *packngo.ErrorResponse
if errors.As(err, &errResp) && errResp.Response != nil {
if errResp.Response.StatusCode == http.StatusNotFound {
if resp != nil {
if resp.StatusCode == http.StatusNotFound {
// When the server does not exist we do not have anything left to do.
// Probably somebody manually deleted the server from the UI or via API.
log.Info("Server not found by id, nothing left to do")
controllerutil.RemoveFinalizer(packetmachine, infrav1.MachineFinalizer)
return ctrl.Result{}, nil
}

if errResp.Response.StatusCode == http.StatusForbidden {
if resp.StatusCode == http.StatusForbidden {
// When a server fails to provision it will return a 403
log.Info("Server appears to have failed provisioning, nothing left to do")
controllerutil.RemoveFinalizer(packetmachine, infrav1.MachineFinalizer)
Expand All @@ -476,7 +482,8 @@ func (r *PacketMachineReconciler) reconcileDelete(ctx context.Context, machineSc
return ctrl.Result{}, fmt.Errorf("%w: %s", ErrMissingDevice, packetmachine.Name)
}

if _, err := r.PacketClient.Devices.Delete(device.ID, force); err != nil {
apiRequest := r.PacketClient.DevicesApi.DeleteDevice(nil, *device.Id).ForceDelete(force)
if _, err := apiRequest.Execute(); err != nil {
return ctrl.Result{}, fmt.Errorf("failed to delete the machine: %w", err)
}

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ module sigs.k8s.io/cluster-api-provider-packet
go 1.17

require (
github.com/equinix-labs/metal-go v0.6.0
github.com/onsi/gomega v1.20.2
github.com/packethost/packngo v0.26.0
github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.5.0
github.com/spf13/pflag v1.0.5
Expand Down
14 changes: 8 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,6 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dnaeon/go-vcr v1.0.1 h1:r8L/HqC0Hje5AXMu1ooW8oyQyOFv4GxqpL0nRP7SLLY=
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68=
github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
Expand All @@ -174,6 +172,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/equinix-labs/metal-go v0.6.0 h1:rX5XnPt95HlDMtITSjwQjqFzu1AKQqCult/9uy/lFNw=
github.com/equinix-labs/metal-go v0.6.0/go.mod h1:uTuxWkVf/wl9VUBYnCtecRtHfdTCeajDwgzluSZBD7U=
github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ=
github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84=
Expand Down Expand Up @@ -506,8 +506,6 @@ github.com/onsi/gomega v1.20.2/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8lu
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/packethost/packngo v0.26.0 h1:jbPHPEd+KpoM2OBQ3EgbgEYiAUK7vpZ9XhqOMEbnk78=
github.com/packethost/packngo v0.26.0/go.mod h1:/UHguFdPs6Lf6FOkkSEPnRY5tgS0fsVM+Zv/bvBrmt0=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pborman/uuid v0.0.0-20170612153648-e790cca94e6c/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
Expand Down Expand Up @@ -610,13 +608,18 @@ github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
Expand Down Expand Up @@ -694,7 +697,6 @@ golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200420201142-3c4aac89819a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
Expand Down
Loading

0 comments on commit 3740c6b

Please sign in to comment.