How to add object mask to call GetNetworkVlans using golang - go

func getPrivateVlan(env string) (string, error) {
// 1. Create a session
sess := session.New(user, pass)
// 2. Get a service
accountService := services.GetAccountService(sess)
// 3. Invoke a method:
vlans, err := accountService.GetNetworkVlans()
vlan := vlans[0]
log.Println(*vlan.Name) //works
log.Println(*vlan.PrimaryRouter) //Doesn't work
}
The object returned is an array of vlans of type SoftLayer_Network_Vlan, https://sldn.softlayer.com/reference/datatypes/softlayer_network_vlan.
I am able to access the properties in column "Local Properties" (ie Name) but am unable to access the properties in column "Relational & Count Properties" (ie PrimaryRouter).
How can I add an object mask to my call in order to see these properties?

The reason is that in order to obtain relational data from an object in the API you must declare an object mask in your API call, as far as I can see, it is not declared in your code, it should be something like this:
func getPrivateVlan(env string) (string, error) {
// 1. Create a session
sess := session.New(user, pass)
// 2. Get a service
accountService := services.GetAccountService(sess)
//declare Mask
object_mask := "id;name;primaryRouter"
// 3. Invoke a method including the Object mask:
vlans, err := accountService.Mask(object_mask).GetNetworkVlans()
vlan := vlans[0]
log.Println(*vlan.Name) //works
log.Println(*vlan.PrimaryRouter) //
}
Try the following code for example:
package main
import (
"fmt"
"github.com/softlayer/softlayer-go/services"
"github.com/softlayer/softlayer-go/session"
"encoding/json"
)
func main() {
// SoftLayer API username and key
username := "set-me"
apikey := "set-me"
// Create a session
sess := session.New(username, apikey)
// Get SoftLayer_Account service
service := services.GetAccountService(sess)
// Object-Mask to get specific Vlan's information
mask := "id;name;primaryRouter"
// Call to getNetworkVlans in order to retrieve vlans according to filter.
result, err := service.Mask(mask).GetNetworkVlans()
if err != nil {
fmt.Printf("\n Unable to retrieve vlans:\n - %s\n", err)
return
}
// Following helps to print the result in json format.
jsonFormat, jsonErr := json.MarshalIndent(result,""," ")
if jsonErr != nil {
fmt.Println(jsonErr)
return
}
fmt.Println(string(jsonFormat))
}
For more information please see below:
https://sldn.softlayer.com/article/object-masks#Property_Set

source: Unable to get itemCategory info from call GetConfiguration when called from golang
F.Ojeda:
The default endpoint is REST but in your environment you are using xmlrpc, which is probably due to the existence of the ~ / .softlayer file and in this it is configured as an XMLRPC enpoint.
For more information you can see the following documentation: https://github.com/softlayer/softlayer-go
This issue happens for the XMLRPC enpoint and you can report it in the go GitHub. https://github.com/softlayer/softlayer-go/issues/
Try in your code with the REST endpoint, like this example:
endpoint := "https://api.softlayer.com/rest/v3"
// Create a session
sess := session.New(username, apikey, endpoint)

Related

Manually extracting OpenTelemetry context from golang into a string?

I'm building a simple client server app which I want to trace across the client execution to a server microservice that calls a second server microservice.
Simply speaking, it's not more complicated than CLI -> ServiceA -> ServiceB.
The challenge I'm having is how to serialize the context - most of the docs I've looked at appear to do some form of automated HTTP header injection (e.g. https://opentelemetry.lightstep.com/core-concepts/context-propagation/) , but I do not have access to that. I need to serialize (I think) the context of the trace/span in the client and push it to the server, where I'll rehydrate it. (Mind you, I'd love this to be simpler, but I cannot figure it out).
So the object looks like this (called "job"):
args := &types.SubmitArgs{
SerializedOtelContext: serializedOtelContext,
}
job := &types.Job{}
tracer := otel.GetTracerProvider().Tracer("myservice.org")
_, span := tracer.Start(ctx, "Submitting Job to RPC")
err := system.JsonRpcMethod(rpcHost, rpcPort, "Submit", args, job)
The function to submit to JsonRpcMethod is here:
func JsonRpcMethod(
host string,
port int,
method string,
req, res interface{},
) error {
client, err := rpc.DialHTTP("tcp", fmt.Sprintf("%s:%d", host, port))
if err != nil {
return fmt.Errorf("Error in dialing. %s", err)
}
return client.Call(fmt.Sprintf("JobServer.%s", method), req, res)
}
And the function that receives it is here:
func (server *JobServer) Submit(args *types.SubmitArgs, reply *types.Job) error {
//nolint
job, err := server.RequesterNode.Scheduler.SubmitJob(args.Spec, args.Deal)
if err != nil {
return err
}
*reply = *job
return nil
}
My question is how do I, in the receiving function ("Submit" above) extract the trace/span from the sender?
Here is a small program to illustrate the usage. Hope this makes it clear.
package main
import (
"context"
"fmt"
"go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
"go.opentelemetry.io/otel/propagation"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
)
func main() {
// common init
// You may also want to set them as globals
exp, _ := stdouttrace.New(stdouttrace.WithPrettyPrint())
bsp := sdktrace.NewSimpleSpanProcessor(exp) // You should use batch span processor in prod
tp := sdktrace.NewTracerProvider(
sdktrace.WithSampler(sdktrace.AlwaysSample()),
sdktrace.WithSpanProcessor(bsp),
)
propgator := propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{})
ctx, span := tp.Tracer("foo").Start(context.Background(), "parent-span-name")
defer span.End()
// Serialize the context into carrier
carrier := propagation.MapCarrier{}
propgator.Inject(ctx, carrier)
// This carrier is sent accros the process
fmt.Println(carrier)
// Extract the context and start new span as child
// In your receiving function
parentCtx := propgator.Extract(context.Background(), carrier)
_, childSpan := tp.Tracer("foo").Start(parentCtx, "child-span-name")
childSpan.AddEvent("some-dummy-event")
childSpan.End()
}

How do I generate a token with TTL 8h from the below golang function?

I am new in programming and have no idea about using the the token generate client api function in the source code from my client side golang program. Looking for some advice. Thank you so much.
Source code package: https://pkg.go.dev/github.com/gravitational/teleport/api/client#Client.UpsertToken
Function Source Code:
func (c *Client) UpsertToken(ctx context.Context, token types.ProvisionToken) error {
tokenV2, ok := token.(*types.ProvisionTokenV2)
if !ok {
return trace.BadParameter("invalid type %T", token)
}
_, err := c.grpc.UpsertToken(ctx, tokenV2, c.callOpts...)
return trail.FromGRPC(err)
}
My code:
package main
import (
"context"
"crypto/tls"
"fmt"
"log"
"os"
"strings"
"time"
"github.com/gravitational/teleport/api/client"
"github.com/gravitational/teleport/api/client/proto"
"google.golang.org/grpc"
)
// Client is a gRPC Client that connects to a Teleport Auth server either
// locally or over ssh through a Teleport web proxy or tunnel proxy.
//
// This client can be used to cover a variety of Teleport use cases,
// such as programmatically handling access requests, integrating
// with external tools, or dynamically configuring Teleport.
type Client struct {
// c contains configuration values for the client.
//c Config
// tlsConfig is the *tls.Config for a successfully connected client.
tlsConfig *tls.Config
// dialer is the ContextDialer for a successfully connected client.
//dialer ContextDialer
// conn is a grpc connection to the auth server.
conn *grpc.ClientConn
// grpc is the gRPC client specification for the auth server.
grpc proto.AuthServiceClient
// closedFlag is set to indicate that the connnection is closed.
// It's a pointer to allow the Client struct to be copied.
closedFlag *int32
// callOpts configure calls made by this client.
callOpts []grpc.CallOption
}
/*
type ProvisionToken interface {
Resource
// SetMetadata sets resource metatada
SetMetadata(meta Metadata)
// GetRoles returns a list of teleport roles
// that will be granted to the user of the token
// in the crendentials
GetRoles() SystemRoles
// SetRoles sets teleport roles
SetRoles(SystemRoles)
// GetAllowRules returns the list of allow rules
GetAllowRules() []*TokenRule
// GetAWSIIDTTL returns the TTL of EC2 IIDs
GetAWSIIDTTL() Duration
// V1 returns V1 version of the resource
V2() *ProvisionTokenSpecV2
// String returns user friendly representation of the resource
String() string
}
type ProvisionTokenSpecV2 struct {
// Roles is a list of roles associated with the token,
// that will be converted to metadata in the SSH and X509
// certificates issued to the user of the token
Roles []SystemRole `protobuf:"bytes,1,rep,name=Roles,proto3,casttype=SystemRole" json:"roles"`
Allow []*TokenRule `protobuf:"bytes,2,rep,name=allow,proto3" json:"allow,omitempty"`
AWSIIDTTL Duration `protobuf:"varint,3,opt,name=AWSIIDTTL,proto3,casttype=Duration" json:"aws_iid_ttl,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
*/
func main() {
ctx := context.Background()
args := os.Args[1:]
nodeType := ""
if len(args) > 0 {
nodeType = args[0]
}
proxyAddress := os.Getenv("TELEPORT_PROXY")
if len(proxyAddress) <= 0 {
proxyAddress = "proxy.teleport.example.local:443"
}
clt, err := client.New(ctx, client.Config{
Addrs: []string{
"proxy.teleport.example.local:443",
"proxy.teleport.example.local:3025",
"proxy.teleport.example.local:3024",
"proxy.teleport.example.local:3080",
},
Credentials: []client.Credentials{
client.LoadProfile("", ""),
},
})
if err != nil {
log.Fatalf("failed to create client: %v", err)
}
defer clt.Close()
ctx, err, token, err2 := clt.UpsertToken(ctx, token)
if err || err2 != nil {
log.Fatalf("failed to get tokens: %v", err)
}
now := time.Now()
t := 0
fmt.Printf("{\"tokens\": [")
for a, b := range token {
if strings.Contains(b.GetRoles(), b.Allow().String(), b.GetAWSIIDTTL(), nodeType) {
if t >= 1 {
fmt.Printf(",")
} else {
panic(err)
}
expiry := "never" //time.Now().Add(time.Hour * 8).Unix()
_ = expiry
if b.Expiry().Unix() > 0 {
exptime := b.Expiry().Format(time.RFC822)
expdur := b.Expiry().Sub(now).Round(time.Second)
expiry = fmt.Sprintf("%s (%s)", exptime, expdur.String())
}
fmt.Printf("\"count\": \"%1d\",", a)
fmt.Printf(b.Roles(), b.GetAllowRules(), b.GetAWSIIDTTL(), b.GetMetadata().Labels)
}
}
}
Output:
Syntax error instead of creating a token
It's seems your code have many mistake. And, It's very obvious you are getting syntax error. I am sure you would have got the line number in the console where actually these syntax error has occurred.
Please understand the syntax of Golang and also how to call the functions and how many parameter should i pass to those functions.
There are few mistakes i would like to point out after reviewing your code.
//It shouldn't be like this
ctx, err, token, err2 := clt.UpsertToken(ctx, token)
//Instead it should be like this
err := clt.UpsertToken(ctx, token)
//The return type of UpsertToken() method is error, you should use only one variable to receive this error.
strings.Contains() function takes two argument but you are passing four.
Refer this document for string.Contains()
You are assigning t := 0 and checking it with if condition inside for loop and never incremented.
Refer this document for fmt.Printf()
Refer this for function
Remove all the syntax error then only your code will run also cross check your logic.
If you want to see the example of syntax error then check here : https://go.dev/play/p/Hhu48UqlPRF

golang cgi + apache login session management

I am new to golang. I want to use golang as cgi for my apache server. I dont want to run my golang program as a listener/server. I write .go files for each action such as login.go, logout.go, welcome.go and compile them into individual exes. I rename the exes into cgi and put them in the cgi-bin folder of apache and post from my html file to cgi bin folder. I want my go lang to serve through apache.
This is my simple html form
<html>
<head><title>Go Test</title></head>
<body>
<form action='cgi-bin/login.cgi' method='post'>
username : <input name='username' value='vimal'><br>
password : <input name='password' value='hello'><br>
<input type='submit' value='submit'>
</form>
</body>
</html>
This is my golang source for login. I compile into login.exe rename it to login.cgi and put it in cgibin folder of apache.
package main
import (
"net/http/cgi"
"net/http"
"fmt"
)
var (
// key must be 16, 24 or 32 bytes long (AES-128, AES-192 or AES-256)
// key = []byte("super-secret-key")
key = uuid.NewV4().String()
store = sessions.NewCookieStore(key)
)
func errorResponse(code int, msg string) {
fmt.Printf("Status:%d %s\r\n", code, msg)
fmt.Printf("Content-Type: text/plain\r\n")
fmt.Printf("\r\n")
fmt.Printf("%s\r\n", msg)
}
func main() {
var req *http.Request
var w *http.ResponseWriter
var err error
req, err = cgi.Request()
if err != nil {
errorResponse(500, "cannot get cgi request" + err.Error())
return
}
if err := req.ParseForm(); err != nil {
errorResponse(500, "cannot get cgi request" + err.Error())
}
username := req.FormValue("username")
password := req.FormValue("password")
//create session
//store session variables like user id, user name etc., that can be accessed through other .cgi files like welcome.cgi
// Use req to handle request
fmt.Printf("Content-type: text/html\n\n")
fmt.Printf("<!DOCTYPE html>\n")
fmt.Printf("<p>username: %s\n",username)
fmt.Printf("<p>password: %s\n",password)
fmt.Printf("req=%v\r\n", req)
}
I need help to create a session and store session variables like user id, username etc.,
If my another golang cgi file welcome.cgi is called it should be able to access the session variables like user id, name and print them
Please provide me with complete code. I am new to golang.
I dont want to use my golang as server. I just want to make small cgi pages.
Thanks
You can use normal handlers like the ones used in several examples on the internet, that way you don't need to use a series of fmt.Printf to send data to the CGI server. One way that I found easy to work is by using the cgi.Serve function which can be used in conjunction with an http.HandlerFunc. Using http.HandlerFunc or http.Handler will allow you to use any session manager implementation in go that uses http.ResponseWriter and http.Request. Note however that you should not initialize your store with a randomly generated key from inside your program, and also, if you use a database back-end you will not be able to use connection polling directly from go, since your program main function will be executed on each request and it should open an close connections on each invocation.
Following is a simple example that uses the approach discussed above:
package main
import (
"encoding/hex"
"fmt"
"io"
"net/http"
"net/http/cgi"
"os"
"github.com/gorilla/sessions"
)
func main() {
// Use Serve function with an anonymous function, you can also use instances
// of http.Handler. The function does not need to be an anonymous function, it
// just has to match the HandlerFunc signature
err := cgi.Serve(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
// Get the session auth key from a trusted source,
// in this example an env var is used. You can use any mechanism you want
// so long that you don't generate it from within this program
key, _ := hex.DecodeString(os.Getenv("SESSION_AUTH_KEY"))
store := sessions.NewCookieStore(key)
// Get a session from the store if any
sess, err := store.Get(r, "mysess")
if err != nil {
io.WriteString(rw, fmt.Sprintf("error reading cookies: %v", err))
return
}
if sess.IsNew {
sess.Values["val"] = 1
//Save your store before writing anything to the client
if err := sess.Save(r, rw); err != nil {
io.WriteString(rw, "error writing sesion")
} else {
io.WriteString(rw, "new session")
}
return
}
//Write session values to validate that your session is working
io.WriteString(rw, "Values:")
for name, value := range sess.Values {
io.WriteString(rw, fmt.Sprintf("name: %s, val: %v", name, value))
}
}))
if err != nil {
fmt.Fprintf(os.Stderr, "Error :%v", err)
}
}

How do I set the S3 Request Payer option when using the aws-sdk-v2?

I am trying to use the aws-sdk-go-v2 to retrieve some data from an S3 bucket. In order to do so I need to be able to set the Request Payer option, however, since I am new to using the SDK, I have no idea how to do so.
I've tried setting this as an env variable AWS_REQUEST_PAYER=requester, but scanning the source code for this golang SDK quickly, I couldn't find that it would be picked up by the SDK as an option.
Using the SDK as directed also fails with an Unauthorized response:
import (
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/feature/s3/manager"
"github.com/aws/aws-sdk-go-v2/service/s3"
)
type awsArchive struct {
bucket string
config config.Config
client *s3.Client
}
func (s *awsArchive) download(uri string, dest string) error {
downloader := manager.NewDownloader(s.client)
paginator := s3.NewListObjectsV2Paginator(s.client, &s3.ListObjectsV2Input{
Bucket: &s.bucket,
Prefix: &uri,
})
for paginator.HasMorePages() {
page, err := paginator.NextPage(context.TODO())
if err != nil {
return err
}
for _, obj := range page.Contents {
if err := downloadToFile(downloader, dest, s.bucket, aws.ToString(obj.Key)); err != nil {
return err
}
}
}
return nil
}
func downloadToFile(downloader *manager.Downloader, targetDirectory, bucket, key string) error {
// Create the directories in the path
file := filepath.Join(targetDirectory, key)
if err := os.MkdirAll(filepath.Dir(file), 0775); err != nil {
return err
}
// Set up the local file
fd, err := os.Create(file)
if err != nil {
return err
}
defer fd.Close()
// Download the file using the AWS SDK for Go
fmt.Printf("Downloading s3://%s/%s to %s...\n", bucket, key, file)
_, err = downloader.Download(context.TODO(), fd, &s3.GetObjectInput{Bucket: &bucket, Key: &key})
return err
}
Error: operation error S3: ListObjectsV2, https response error StatusCode: 403, RequestID: ..., HostID: ..., api error AccessDenied: Access Denied
Would anyone be able to provide me with an example of using the Golang SDK to get S3 files from a Requestor Pays enabled bucket please, i.e. the equivalent of:
aws s3 sync --request-payer requester source_bucket destination_folder
It seems you can use field named 'RequestPayer' in the GetObjectInput struct. Found it from pkg document.
From the link:
type GetObjectInput struct {
// The bucket name containing the object. When using this action with an access
...
Bucket *string
// Key of the object to get.
// This member is required.
Key *string
...
...
// Confirms that the requester knows that they will be charged for the request.
// Bucket owners need not specify this parameter in their requests. For information
// about downloading objects from requester pays buckets, see Downloading Objects
// in Requestor Pays Buckets
// (https://docs.aws.amazon.com/AmazonS3/latest/dev/ObjectsinRequesterPaysBuckets.html)
// in the Amazon S3 Developer Guide.
RequestPayer types.RequestPayer
You can refer to 'RequestPayer' definition here.

Can you edit vsi bandwith allocation via virtual.go:EditObject()?

I am using a modified version of this script: https://softlayer.github.io/go/edit_virtual_guest.go/
The script is the same except my objectTemplate looks like:
var objectTemplate datatypes.Virtual_Guest
objectTemplate.BandwidthAllocation = sl.Float(250)
The output after running is "Virtual Guest Server was successfully edited" but my vsi does not show updated bandwidth in the ui.
Is it possible to edit bandwidth using the EditObject call? Is it possible to edit the bandwidth using a different api call?
The “bandwidthAllocation” attribute that you are using does not work to edit the bandwidth of a virtual server, I suggest you to use SoftLayer_Product_Order::placeOrder to upgrade your bandwidth because the control portal use this method and service to do that.
There is not possible to edit bandwidth using the EditObject call.
This is a go example that you can use to upgrade your bandwidth:
/*
Upgrade bandwidth of a virtual server.
Build a SoftLayer_Container_Product_Order_Virtual_Guest object for a new virtual server order and
pass it to the SoftLayer_Product_Order API service to order it.
See below for more details.
Important manual pages:
http://sldn.softlayer.com/reference/services/SoftLayer_Product_Order/verifyOrder
http://sldn.softlayer.com/reference/services/SoftLayer_Product_Order/placeOrder
http://sldn.softlayer.com/reference/datatypes/SoftLayer_Virtual_Guest
http://sldn.softlayer.com/reference/datatypes/SoftLayer_Container_Product_Order
https://softlayer.github.io/reference/datatypes/SoftLayer_Container_Product_Order_Virtual_Guest_Upgrade/
License: http://sldn.softlayer.com/article/License
Author: SoftLayer Technologies, Inc. <sldn#softlayer.com>
*/
package main
import (
"fmt"
"github.com/softlayer/softlayer-go/datatypes"
"github.com/softlayer/softlayer-go/services"
"github.com/softlayer/softlayer-go/session"
"github.com/softlayer/softlayer-go/sl"
"encoding/json"
)
func main() {
// SoftLayer API username and key
username := "set me"
apikey := "set me"
// Declare the id for the virtual server you wish to order.
vmId := 11111
// Build a skeleton SoftLayer_Virtual_Guest object.
virtualGuests := []datatypes.Virtual_Guest {
{ // id of SoftLayer_Virtual_Guest object
Id: sl.Int(vmId),
},
}
// Build a skeleton SoftLayer_Product_Item_Price objects. To get the list of valid
// prices for the package use the SoftLayer_Product_Package:getItems method
prices := []datatypes.Product_Item_Price {
{ Id: sl.Int(50231) }, // 1000 GB Bandwidth
}
properties := []datatypes.Container_Product_Order_Property{
{
Name: sl.String("NOTE_GENERAL"),
Value: sl.String("upgrade bandwidth"),
},
{
Name: sl.String("MAINTENANCE_WINDOW"),
Value: sl.String("2018-07-26T19:20:14.743Z"),
},
{
Name: sl.String("orderOrigin"),
Value: sl.String("control"),
},
}
// Build a Container_Product_Order object containing the order you wish to place.
orderTemplate := datatypes.Container_Product_Order{
ComplexType : sl.String("SoftLayer_Container_Product_Order_Virtual_Guest_Upgrade"),
VirtualGuests : virtualGuests,
Prices : prices,
Properties: properties,
}
hardwareContainer := datatypes.Container_Product_Order_Hardware_Server{
Container_Product_Order: orderTemplate,
}
virtualGuestContainer := datatypes.Container_Product_Order_Virtual_Guest{
Container_Product_Order_Hardware_Server: hardwareContainer,
}
orderContainer := &datatypes.Container_Product_Order_Virtual_Guest_Upgrade{
Container_Product_Order_Virtual_Guest: virtualGuestContainer,
}
// Create a session
sess := session.New(username, apikey)
// Get SoftLayer_Product_Order service
service := services.GetProductOrderService(sess)
// Use verifyOrder() method to check for errors. Replace this with placeOrder() when
// you are ready to order.
receipt, err := service.VerifyOrder(orderContainer)
if err != nil {
fmt.Printf("\n Unable to place order:\n - %s\n", err)
return
}
// Following helps to print the result in json format.
jsonFormat, jsonErr := json.MarshalIndent(receipt, "", " ")
if jsonErr != nil {
fmt.Println(jsonErr)
return
}
fmt.Println(string(jsonFormat))
}
To get the item prices and their respective locations available you can use the following example:
/*
GetItemPrices
Retrieve a collection of SoftLayer_Product_Item_Prices that are valid for this package.
Important manual pages:
https://softlayer.github.io/reference/services/SoftLayer_Product_Package/getItemPrices/
License: http://sldn.softlayer.com/article/License
Author: SoftLayer Technologies, Inc. <sldn#softlayer.com>
*/
package main
import (
"fmt"
"github.com/softlayer/softlayer-go/services"
"github.com/softlayer/softlayer-go/session"
"encoding/json"
"terraform-provider-softlayer/softlayer"
)
func main() {
softlayer.Provider()
// SoftLayer API username and key
username := "set me"
apikey := "set me"
packageId := 46
mask := "id;locationGroupId;item[id,keyName,description];pricingLocationGroup[locations[id, name, longName]]"
// Create a session
sess := session.New(username, apikey)
service := services.GetProductPackageService(sess)
receipt, err := service.Id(packageId).Mask(mask).GetItemPrices()
if err != nil {
fmt.Printf("\n Unable to retrieve the item prices:\n - %s\n", err)
return
}
// Following helps to get the result in json format.
// Following helps to print the result in json format.
jsonFormat, jsonErr := json.MarshalIndent(receipt, "", " ")
if jsonErr != nil {
fmt.Println(jsonErr)
return
}
fmt.Println(string(jsonFormat))
}

Resources