access golang struct field with variable - go

For reference: example here
I am trying to access a struct field using a variable key, to explain in PHP you can do the below.
$arr = ["test" => "foo"];
$key = "test";
$result = $arr[$key];
Or in Javascript you can do the below
const obj = {"test": "foo"}
const key = "test"
const result = obj[key]
Is this possible with go structs? I have searched for this functionality, but the answers always seem to point to the reflect package and running a for loop over the struct fields.
My code (linked above) gets the compile error of invalid operation: p[key] (type Post does not support indexing) which makes sense, but I can't find a way around this.

One of the main points when using structs is that the way how to access the fields is known at compile time.Then the produced code uses fixed indexes added to a base address of the struct.
For any kind of dynamism here you just need to use map[string]string or similar.

Related

How to represent golang "any" type in protobuf language

am using a protobuf definition file to create golang classes
file.proto
message my_message {
<what type to use?> data = 1 [json_name = "data"]
}
generated.go
type MyMessage struct {
data any
}
I have checked out Struct , Value and Any, though none of them actually mark the type as “any” in generated classes.
The closes I get is Value type which can accomodate primitives as well as structs and lists.
As far as I'm aware the Go code generator doesn't have any circumstances where any/interface{} will be used for a generated field.
google.protobuf.Any is likely what you want here, but the field in the generated code will of type anypb.Any. If you absolutely require the any type be used, you'll unfortunately have to manually map to another struct.

K8s operator read raw data

Im trying to get RAW data from operator CR and im getting an empty object . (all others value are working as expected )
I’ve created a minimal example for the issue, in the example im trying to read the infrastructureConfig object
The tricky part here that my struct is reference to another struct which have a property type rawdata
https://github.com/JennyMet/gardner_test
Here the simple CR
https://github.com/JennyMet/gardner_test/blob/main/config/samples/mygroup_v1alpha1_rawtest.yaml#L11
Here im tying to read the data and get an empty object, any idea?
https://github.com/JennyMet/gardner_test/blob/main/controllers/rawtest_controller.go#L70
this is the reference of the type which im using
https://github.com/gardener/gardener/blob/5522be0e17ccf38aae36efb9fdb6463c66d6e4f1/pkg/apis/core/v1beta1/types_shoot.go#L1184
I think its related to fields
x-kubernetes-preserve-unknown-fields: true
https://book.kubebuilder.io/reference/markers/crd-processing.html
which is not existing
How can I add it to the schema here ?
https://github.com/JennyMet/gardner_test/blob/main/api/v1alpha1/rawtest_types.go#L32 as under the hood it uses
https://github.com/gardener/gardener/blob/5522be0e17ccf38aae36efb9fdb6463c66d6e4f1/pkg/apis/core/v1beta1/types_shoot.go#L1184
I mean I tried and it doesnt work as the InfrastructureConfig which is RAW is under the
type System struct {
Type system `json:"type,omitempty"`
// +kubebuilder:pruning:PreserveUnknownFields
Provider v1beta1.Provider `json:"provider,omitempty"`
}
But the rawData is under Provider which is not my struct, im just using it.
which is like this , see the InfrastructureConfig type...
type Provider struct {
Type string `json:"type" protobuf:"bytes,1,opt,name=type"`
ControlPlaneConfig *runtime.RawExtension `json:"controlPlaneConfig,omitempty" protobuf:"bytes,2,opt,name=controlPlaneConfig"`
InfrastructureConfig *runtime.RawExtension `json:"infrastructureConfig,omitempty" protobuf:"bytes,3,opt,name=infrastructureConfig"`
}
Currently, you can only put the // +kubebuilder:pruning:PreserveUnknownFields on the Provider v1beta1.Provider, which means all sub fields in it will be allowed with additional unknown fields.
The good news is, your problem will be solved after https://github.com/kubernetes-sigs/controller-tools/pull/683 merged. After that, you have not to use // +kubebuilder:pruning:PreserveUnknownFields and controller-tools would automatically add x-kubernetes-preserve-unknown-fields: true for all RawExtension fields.

parse simple terraform file using go

I now tried, everything but cant get this simple thing to work.
I got the following test_file.hcl:
variable "value" {
test = "ok"
}
I want to parse it using the following code:
package hcl
import (
"github.com/hashicorp/hcl/v2/hclsimple"
)
type Config struct {
Variable string `hcl:"test"`
}
func HclToStruct(path string) (*Config, error) {
var config Config
return &config, hclsimple.DecodeFile(path, nil, &config)
But I receive:
test_file.hcl:1,1-1: Missing required argument; The argument "test" is required, but no definition was found., and 1 other diagnostic(s)
I checked with other projects using the same library but I cannot find my mistake .. I just dont know anymore. Can someone guide me into the right direction?
The Go struct type you wrote here doesn't correspond with the shape of the file you want to parse. Notice that the input file has a variable block with a test argument inside it, but the Go type you wrote has only the test argument. For that reason, the HCL parser is expecting to find a file with just the test argument at the top-level, like this:
test = "ok"
To parse this Terraform-like structure with hclsimple will require you to write two struct types: one to represent the top level body containing variable blocks and another to represent the content of each of the blocks. For example:
type Config struct {
Variables []*Variable `hcl:"variable,block"`
}
type Variable struct {
Test *string `hcl:"test"`
}
With that said, I'll note that the Terraform language uses some features of HCL that hclsimple can't support, or at least can't support with direct decoding like this. For example, the type argument inside variable blocks is a special sort of expression called a type constraint which hclsimple doesn't support directly, and so parsing it will require using the lower-level HCL API. (That's what Terraform is doing internally.)
Thanks to #Martin Atkins, I now have the following code that works:
type Config struct {
Variable []Variable `hcl:"variable,block"`
}
type Variable struct {
Value string `hcl:"name,label"`
Test string `hcl:"test"`
}
With that I can parse a variables.tf like:
variable "projectname" {
default = "cicd-template"
}
variable "ansibleuser" {
default = "centos"
}

Is there a way to have a dynamic type slice in Go?

I have a standard response built in PHP for microservices that I want to replicate in Go.
In particular, the "data" element of the response array can have anything.
Example
$response['data'] = [];
$response['data']['entities'] = [ objects that implements toArray() ]
$response['data']['quantity'] = 1
Problem is that Data differs per endpoint.
So one option I was thinking is in each endpoint (controller, action, etc) declare a Data struct that I would use in the StandardResponse.Data struct.
But how can I achieve that? Using interfaces?
Sorry I am new to Go.
An interface{} is one way to do it. Something like:
type StandardResponse struct {
Error bool
ErrorMsg string
Data interface{}
}
Marshaling this to JSON will work assuming the underlying type of interface{} supports it.

Reason React and Graphql handling ENUM values

Just started to learn reason react and struggle with a graphql setup trying to read an ENUM value.
setup
reason react
apollo graphql
graphql_ppx
github graphql endpoint
i am fetching the latest pull request data over the github api and reading the status property which is an enum and defined in the gql docs as:
OPEN
CLOSED
MERGED
checking the network tab, i see the states are received as strings. within the application when I log the field i get a bunch of integers reflecting the values. can smb explain me, how i can "print" the data as string to my view and why they are translated to integers? is there somewhere a type generated which i could use for a variant switch?
let stateEnum = data->map(node => node##state);
Js.log(stateEnum) // possible values: 880069578, 982149804 or -1059826260
// somehow switch these values here?! :)
// current type of `stateEnum` is option('a)
thanks a lot in advance and have a nice day!
GraphQL Enums are represented as Reason polymorphic variants. Under the hood, in runtime, they are just integers. If you want to display them to the user you have two options:
1. Map them to string by hand using a switch
let status =
switch(node#status) {
| `OPEN => “Open”
// other cases
}
You can use BuckleScript functionality do generate jsConverters:
[#bs.deriving jsConverter]
type status = [ |`OPEN | `CLOSED /* other cases */]
this will generate two functions for you: statusToJs and statusFromJs. They help you convert variant to and from string.
Here is BuckleScript documentation about it: https://bucklescript.github.io/docs/en/generate-converters-accessors#convert-between-js-string-enum-and-bs-polymorphic-variant
As #Herku mentioned in his comment, the key was just to do this:
// asume that your enum is on a gqp property called `state`
// and we use the built in lib `Belt.Option` and the fn `getWithDefault`
// this way we are sure, that `stateEnum` is defined with one of the valid enum values
let stateEnum = data->map(node => node##state)->getWithDefault(`OPEN);
// next we switch the polymorphic variant
let state = switch(stateEnum) {
| `OPEN => "open"
| `CLOSED => "close"
| `MERGED` => "merged"
}
// str = let str = ReasonReact.string;
str(state);

Resources