How to get vCenter version using govmomi client API? - go

I have a go client initialized to connect to a vCenter as follows. I am trying to get the version of the vCenter using the client. I did not find a very good source for this.
Which arguments to use inside retrieve() API to get the version and other information related to vCenter cluster?
import (
"context"
"fmt"
"net/url"
"github.com/vmware/govmomi"
)
func main() {
vURL := url.URL{
Scheme: "https",
Host: "10.30.8.34",
Path: "sdk",
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
client, err := govmomi.NewClient(ctx, vURL, true)
if err != nil {
fmt.Printf("Logging in error: %s\n", err.Error())
return
}
fmt.Println("Log in successful")
client.Logout(ctx)
}

Are you looking for VsanHostConfigInfoEx?
type VsanHostConfigInfoEx struct {
types.VsanHostConfigInfo
EncryptionInfo *VsanHostEncryptionInfo `xml:"encryptionInfo,omitempty"`
DataEfficiencyInfo *VsanDataEfficiencyConfig `xml:"dataEfficiencyInfo,omitempty"`
ResyncIopsLimitInfo *ResyncIopsInfo `xml:"resyncIopsLimitInfo,omitempty"`
ExtendedConfig *VsanExtendedConfig `xml:"extendedConfig,omitempty"`
DatastoreInfo BaseVsanDatastoreConfig `xml:"datastoreInfo,omitempty,typeattr"`
UnmapConfig *VsanUnmapConfig `xml:"unmapConfig,omitempty"`
WitnessHostConfig []VsanWitnessHostConfig `xml:"witnessHostConfig,omitempty"`
InternalExtendedConfig *VsanInternalExtendedConfig `xml:"internalExtendedConfig,omitempty"`
MetricsConfig *VsanMetricsConfig `xml:"metricsConfig,omitempty"`
UnicastConfig *VsanHostServerClusterUnicastConfig `xml:"unicastConfig,omitempty"`
DataInTransitEncryptionInfo *VsanInTransitEncryptionInfo `xml:"dataInTransitEncryptionInfo,omitempty"`
}
which implements VsanHostConfigInfo
type VsanHostConfigInfo struct {
DynamicData
Enabled *bool `xml:"enabled"`
HostSystem *ManagedObjectReference `xml:"hostSystem,omitempty"`
ClusterInfo *VsanHostConfigInfoClusterInfo `xml:"clusterInfo,omitempty"`
StorageInfo *VsanHostConfigInfoStorageInfo `xml:"storageInfo,omitempty"`
NetworkInfo *VsanHostConfigInfoNetworkInfo `xml:"networkInfo,omitempty"`
FaultDomainInfo *VsanHostFaultDomainInfo `xml:"faultDomainInfo,omitempty"`
}

Related

How to created an unbounded input for Beam in Go?

I'm trying to use the Go Beam Sdk to create a pipeline processing pubsub messages.
github.com/apache/beam/sdks/v2/go/pkg/beam
I understand that the pubsubio connector is doing external calls working only on dataflow runner.
What if I want to test my pipeline locally ? How would you do that ?
I need to understand what is preventing me to write my own pubsub unbounded source ? (I may not understand how Beam works under the hood, like how does it serialize user defined code to send it to the runner ?)
Tried to do something like that:
package pubsubio
import (
"context"
"fmt"
cloud_pubsub "cloud.google.com/go/pubsub"
"github.com/apache/beam/sdks/v2/go/pkg/beam"
"github.com/apache/beam/sdks/v2/go/pkg/beam/log"
"github.com/apache/beam/sdks/v2/go/pkg/beam/register"
"github.com/apache/beam/sdks/v2/go/pkg/beam/util/pubsubx"
)
func init() {
register.DoFn3x1[context.Context, string, func(*cloud_pubsub.Message), error](&readFn{})
register.Emitter1[*cloud_pubsub.Message]()
}
type ReadConfig struct {
ProjectID string
TopicName string
SubscriptionName string
}
func Read(
scope beam.Scope,
cfg ReadConfig,
) beam.PCollection {
scope = scope.Scope("pubsubio.Read")
col := beam.Create(scope, cfg.SubscriptionName)
return beam.ParDo(scope, newReadFn(cfg.ProjectID, cfg.TopicName), col)
}
type readFn struct {
pubsubFn
TopicName string
}
func newReadFn(projectID, topicName string) *readFn {
return &readFn{
pubsubFn: pubsubFn{
ProjectID: projectID,
},
TopicName: topicName,
}
}
func (fn *readFn) ProcessElement(
ctx context.Context,
subscriptionName string,
emit func(message *cloud_pubsub.Message),
) error {
log.Info(ctx, "[pubsubio.ProcessElement] Reading from pubsub")
_, err := pubsubx.EnsureTopic(ctx, fn.client, fn.TopicName)
if err != nil {
return fmt.Errorf("cannot get topic: %w", err)
}
sub, err := pubsubx.EnsureSubscription(ctx, fn.client, fn.TopicName, subscriptionName)
if err != nil {
return fmt.Errorf("cannot get subscription: %w", err)
}
return sub.Receive(ctx, func(ctx context.Context, message *cloud_pubsub.Message) {
emit(message)
log.Debugf(ctx, "[pubsubio.ProcessElement] Emit msg: %s", message.ID)
message.Ack()
})
}
So basically I created a Read fn that never return, but the rest of my pipeline is never triggered (I must miss something)

How to validate API key with function in Martini?

So I currently have a function that will take in a string APIKey to check it against my Mongo collection. If nothing is found (not authenticated), it returns false - if a user is found, it returns true. My problem, however, is I'm unsure how to integrate this with a Martini POST route. Here is my code:
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/go-martini/martini"
_ "github.com/joho/godotenv/autoload"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
type User struct {
Name string
APIKey string
}
func validateAPIKey(users *mongo.Collection, APIKey string) bool {
var user User
filter := bson.D{{"APIKey", APIKey}}
if err := users.FindOne(context.TODO(), filter).Decode(&user); err != nil {
fmt.Printf("Found 0 results for API Key: %s\n", APIKey)
return false
}
fmt.Printf("Found: %s\n", user.Name)
return true
}
func uploadHandler() {
}
func main() {
mongoURI := os.Getenv("MONGO_URI")
mongoOptions := options.Client().ApplyURI(mongoURI)
client, _ := mongo.Connect(context.TODO(), mongoOptions)
defer client.Disconnect(context.TODO())
if err := client.Ping(context.TODO(), nil); err != nil {
log.Fatal(err, "Unable to access MongoDB server, exiting...")
}
// users := client.Database("sharex_api").Collection("authorized_users") // commented out when testing to ignore unused warnings
m := martini.Classic()
m.Post("/api/v1/upload", uploadHandler)
m.RunOnAddr(":8085")
}
The validateAPIKey function works exactly as intended if tested alone, I am just unsure how I would run this function for a specific endpoint (in this case, /api/v1/upload).

Keep a MQTT Go client running

I think it is a silly question, I need a MQTT Client to keep running after connection and subscription. I never encountered the problem because my MQTT clients are always coupled with an HTTP server, and when launching a HTTP server, the code don't stop running.
But in the present use case I only need a MQTT Client to subscribe to some topic and stay alive.
Here is what I do (the function just connect to a broker and subcribe to one topic.)
func main() {
godotenv.Load("./.env")
_initMqttConnection()
}
I need the client to stay connected and not stop just after the subscription is done.
How to perform that simple thing ?
Edit 1 : Complete Code
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"path/filepath"
"strings"
"github.com/yosssi/gmq/mqtt"
"github.com/yosssi/gmq/mqtt/client"
"github.com/joho/godotenv"
"github.com/skratchdot/open-golang/open"
)
var cli *client.Client
func _initMqttConnection() {
cli = client.New(&client.Options{
ErrorHandler: func(err error) {
fmt.Println(err)
},
})
defer cli.Terminate()
log.Println("Connecting to " + os.Getenv("mqtt_host"))
err := cli.Connect(&client.ConnectOptions{
Network: "tcp",
Address: os.Getenv("mqtt_host"),
UserName: []byte(os.Getenv("mqtt_user")),
Password: []byte(os.Getenv("mqtt_password")),
ClientID: []byte("mqtt_video_launcher"),
})
if err != nil {
log.Println("Error 1")
panic(err)
}
log.Println("Connected to MQTT")
topic_to_sub := []byte("/" + os.Getenv("video_topic"))
err = cli.Subscribe(&client.SubscribeOptions{
SubReqs: []*client.SubReq{
&client.SubReq{
TopicFilter: topic_to_sub,
QoS: mqtt.QoS0,
Handler: func(topicName, message []byte) {
//do struff with message
fmt.Println(string(topicName), string(message))
},
},
},
})
if err != nil {
panic(err)
}
log.Println("Subscription OK : " + string(topic_to_sub[:len(topic_to_sub)]))
}
func main() {
godotenv.Load("./.env")
_initMqttConnection()
}
The temporary solution I use is adding :
http.ListenAndServe(":", nil)
at the end.
You have to make the program run infinitely or unless you want to explicitly end it (Cntrl c). One good solution that worked for me is to wait for a channel before exiting the main function and that channel can keep listening for an interrupt.
Eg:
func main() {
keepAlive := make(chan os.Signal)
signal.Notify(keepAlive, os.Interrupt, syscall.SIGTERM)
// All your code
<-keepAlive
}

How to update metric values in prometheus exporter (golang)

I'm starting to write an own prometheus exporter using golang.
I think I got the basics but I don't know what to do exactly to get the value of the metric up to date. Using Set only does it once.
It is not changing on runtime.
What I have so far:
package main
import (
"log"
"net/http"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"time"
"io/ioutil"
"github.com/tidwall/gjson"
"strconv"
)
var (
sidekiqProcessed = setGaugeMetric("sidekiq_processed", "Sidekiq Processed", "lable", "lablevalue")
)
func setGaugeMetric(name string, help string, label string, labelvalue string) (prometheusGauge prometheus.Gauge) {
var (
gaugeMetric = prometheus.NewGauge(prometheus.GaugeOpts{
Name: name,
Help: help,
ConstLabels: prometheus.Labels{label: labelvalue},
})
)
return gaugeMetric
}
func getSidekiqProcessed() (sidekiq float64) {
body := getContent("http://example.com/sidekiq/stats")
processed := gjson.Get(body, "sidekiq.processed")
conv, err := strconv.ParseFloat(processed.String(), 64)
if err != nil {
log.Fatal(err)
}
return conv
}
func getContent(url string) (body string) {
httpClient := &http.Client{Timeout: 10 * time.Second}
res, err := httpClient.Get(url)
if err != nil {
log.Fatal(err)
}
content, err := ioutil.ReadAll(res.Body)
res.Body.Close()
if err != nil {
log.Fatal(err)
}
return string(content)
}
func init() {
prometheus.MustRegister(sidekiqProcessed)
}
func main() {
sidekiqProcessed.Set(getSidekiqProcessed())
// The Handler function provides a default handler to expose metrics
// via an HTTP server. "/metrics" is the usual endpoint for that.
http.Handle("/metrics", promhttp.Handler())
log.Fatal(http.ListenAndServe(":8080", nil))
}
Read something about Collector but have no clue how to implement it.
Can somebody help me to complete/correct my code so that the value of the metric also updates at runtime?
Here is an example of custom collector (from https://www.robustperception.io/setting-a-prometheus-counter):
package main
import "github.com/prometheus/client_golang/prometheus"
type MyCollector struct {
counterDesc *prometheus.Desc
}
func (c *MyCollector) Describe(ch chan<- *prometheus.Desc) {
ch <- c.counterDesc
}
func (c *MyCollector) Collect(ch chan<- prometheus.Metric) {
value := 1.0 // Your code to fetch the counter value goes here.
ch <- prometheus.MustNewConstMetric(
c.counterDesc,
prometheus.CounterValue,
value,
)
}
func NewMyCollector() *MyCollector {
return &MyCollector{
counterDesc: prometheus.NewDesc("my_counter_total", "Help string", nil, nil),
}
}
// To hook in the collector: prometheus.MustRegister(NewMyCollector())
You probably want to implement a collector instead, and run the http request when the Prometheus server scrapes. See the best practices.
When implementing the collector for your exporter, you should never use the usual direct instrumentation approach and then update the metrics on each scrape.
Rather create new metrics each time. In Go this is done with MustNewConstMetric in your Update() method. For Python see https://github.com/prometheus/client_python#custom-collectors and for Java generate a List in your collect method, see StandardExports.java for an example.
The github.com/prometheus/client_golang library may be non-trivial to use when writing Prometheus exporters in Go. Try https://pkg.go.dev/github.com/VictoriaMetrics/metrics library instead. It is much easier to use in general. See the following code as an example, which allows dynamically updating sidekiq_processed metric with the given label:
import (
"fmt"
"github.com/VictoriaMetrics/metrics"
)
// UpdateSidekiqProcessed updates `sidekiq_processed{label="<labelValue>"}` metric to the given value
func UpdateSidekiqProcessed(labelValue string, value float64) {
metricName := fmt.Sprintf("sidekiq_processed{label=%q}", labelValue)
metrics.GetOrCreateFloatCounter(metricName).Set(value)
}

unsupported protocol scheme while creating ec2 Security group

I am trying to create security group using goamz.
Below is my code.
package main
import (
"fmt"
"os"
"github.com/mitchellh/goamz/aws"
"github.com/mitchellh/goamz/ec2"
)
type SecurityGroup struct {
Id string `xml:"groupId"`
Name string `xml:"groupName"`
Description string `xml:"groupDescription"`
VpcId string `xml:"vpcId"`
}
func main() {
auth := aws.Auth{
AccessKey: os.Getenv("key"),
SecretKey: os.Getenv("secret"),
}
region := aws.Region{
Name : "us-east-1",
}
ec2conn := ec2.New(auth, region)
fmt.Printf("%+v\n", ec2conn)
resp, err := ec2conn.CreateSecurityGroup(ec2.SecurityGroup{Name: "testing12",
Description: "testing123", VpcId: "vpc-123456"})
fmt.Printf("%+v\n", resp)
if err != nil {
fmt.Printf("%s\n", err.Error())
}
}
And I get the below Response upon execution.
<nil>
Get /? XXXXXXXXX
unsupported protocol scheme ""
I am not sure whether we use any protocol explicitly to create.
Please help me understanding this.

Resources