Files
threshold-plugin-gcp/plugin/service/host/client.go
T
Elim Tsiagbey 779d383a24 feat: OnUpdateSet (#13) & ListHosts (#14)
* feat: OnUpdateSet

Add support for OnUpdateSet with validation. OnUpdateSet will validate he attributes passed to it and run a dryRunValidation with the new set

* feat: ListHosts (#14)

- Update list hosts to only support listing instances
- Update host client to support Instances API
- Add reading IPV6 Address by `Ipv6AccessConfigs`
- Add internal DNS which is the hostname
2024-10-28 13:10:44 -04:00

98 lines
2.7 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package host
import (
"context"
"errors"
"strconv"
computepb "cloud.google.com/go/compute/apiv1/computepb"
pb "github.com/hashicorp/boundary/sdk/pbs/plugin"
"google.golang.org/api/iterator"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
func getInstances(ctx context.Context, instancesClient InstancesAPI, request *computepb.ListInstancesRequest) ([]*computepb.Instance, error) {
hosts := []*computepb.Instance{}
it := instancesClient.List(ctx, request)
for {
resp, err := it.Next()
if err == iterator.Done {
break
}
if err != nil {
return nil, status.Errorf(codes.Unknown, "error listing instances: %s", err)
}
hosts = append(hosts, resp)
}
return hosts, nil
}
func instanceToHost(instance *computepb.Instance) (*pb.ListHostsResponseHost, error) {
if instance.GetId() == 0 {
return nil, errors.New("response integrity error: missing instance id")
}
if instance.GetName() == "" {
return nil, errors.New("response integrity error: missing instance name")
}
result := new(pb.ListHostsResponseHost)
result.ExternalId = strconv.FormatUint(instance.GetId(), 10)
result.ExternalName = instance.GetName()
// Internal DNS name is the hostname of the instance.
// https://cloud.google.com/compute/docs/networking/using-internal-dns
dnsName := instance.GetHostname()
result.DnsNames = appendDistinct(result.DnsNames, &dnsName)
// Now go through all of the interfaces and log the IP address of
// every interface.
for _, iface := range instance.GetNetworkInterfaces() {
// Populate default IP addresses name similar to how we do
// for the entire instance.
result.IpAddresses = appendDistinct(result.IpAddresses, iface.NetworkIP)
for _, external := range iface.AccessConfigs {
result.IpAddresses = appendDistinct(result.IpAddresses, external.NatIP)
result.IpAddresses = appendDistinct(result.IpAddresses, external.ExternalIpv6)
}
// Add the IPv6 addresses.
result.IpAddresses = appendDistinct(result.IpAddresses, iface.Ipv6Address)
if iface.Ipv6AccessConfigs != nil {
for _, external := range iface.Ipv6AccessConfigs {
result.IpAddresses = appendDistinct(result.IpAddresses, external.ExternalIpv6)
}
}
}
// Done
return result, nil
}
// appendDistinct will append the elements to the slice
// if an element is not nil, empty, and does not exist in slice.
func appendDistinct(slice []string, elems ...*string) []string {
for _, e := range elems {
if e == nil || *e == "" || stringInSlice(slice, *e) {
continue
}
slice = append(slice, *e)
}
return slice
}
func stringInSlice(s []string, x string) bool {
for _, y := range s {
if x == y {
return true
}
}
return false
}