Go Testing define custom structure - go

I've followed the structure in a tf file, can you help me to create a proper structure, as I'm new to Go.
Here is tf
ipv4 = {
cidrblock = "10.0.0.0/16"
secondary = [
{
cidrs = "20.0.0.0/16"
enabled = true
},
{
cidrs = "30.0.0.0/16"
enabled = true
}
]
}
So I've an object of strings, as well a list of objects in the main object. I could make a primitive type, for example:
type ipv4 struct {
cidrblock string
cidrs string
enabled bool
}
type ipv6 struct {
border string
generate bool
}
type Sets struct {
Name string
IPv4 *ipv4
IPv6 *ipv6
Tags map[string]string
Tenancy string
}
But I would really like to have a complex structure

you can do something like this:
type ipv4 struct {
cidrblock string
secondary []ipv4secondary
}
type ipv4secondary struct {
cidrblock string
enabled bool
}
and use it as this:
example := ipv4{
cidrblock: "10.0.0.0/16",
secondary: []ipv4secondary{
ipv4secondary{cidrblock: "20.0.0.0/16", enabled: true},
ipv4secondary{cidrblock: "30.0.0.0/16", enabled: true},
},
}
here is the example: https://go.dev/play/p/U7o0BbAis9T

Related

How to change default key names in a struct and delete the rest of items in GO

I need to change the name of the keys in a struct through go.
I have this function
func (p *DbConfig) myfunction(prefix string, namespace string, dbName string, userSecret string) []corev1.EnvVar {
prefix = Underscore(prefix)
namespace = Underscore(namespace)
envs := filter(p.myfunction(prefix), func(item corev1.EnvVar) bool {
if item.Name == "USER" {
return false
}
if item.Name == "PASSWORD" {
return false
}
return true
})
return append(envs, []corev1.EnvVar{
{
Name: prefix + "DB_NAME",
Value: namespace + dbName,
},
{
Name: prefix + "DB_USER",
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: userSecret,
},
Key: "POSTGRES_USER",
},
},
},
{
Name: prefix + "DB_PASSWORD",
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: userSecret,
},
Key: "POSTGRES_PASSWORD",
},
},
},
}...)
}
Where EnVar struct looks like
type EnvVar struct {
Name string `json:"name" protobuf:"bytes,1,opt,name=name"`
Value string `json:"value,omitempty" protobuf:"bytes,2,opt,name=value"`
ValueFrom *EnvVarSource `json:"valueFrom,omitempty" protobuf:"bytes,3,opt,name=valueFrom"`
}
type EnvVarSource struct {
FieldRef *ObjectFieldSelector `json:"fieldRef,omitempty" protobuf:"bytes,1,opt,name=fieldRef"`
ResourceFieldRef *ResourceFieldSelector `json:"resourceFieldRef,omitempty" protobuf:"bytes,2,opt,name=resourceFieldRef"`
ConfigMapKeyRef *ConfigMapKeySelector `json:"configMapKeyRef,omitempty" protobuf:"bytes,3,opt,name=configMapKeyRef"`
SecretKeyRef *SecretKeySelector `json:"secretKeyRef,omitempty" protobuf:"bytes,4,opt,name=secretKeyRef"`
}
and here I need to change the values containing "CONTAINER" with the correct env vars used in the container.
func containerEnvs(hub *immv1alpha1.ImmHub, instance *immv1alpha1.Container) []corev1.EnvVar {
postgresService := hub.Spec.DbConfig.myfunction("CONTAINER_", hub.Namespace, instance.Spec.dbName, instance.Spec.userSecret)
//Here I want to modify the keys of the struct that I need so that correct environment variables are passed
postgresService[0].Name = "DATABASE_NAME"
postgresService[1].Name = "DATABASE_USER"
service := []corev1.EnvVar{
{
Name: "DATABASE_NAME",
Value: instance.Spec.dbName,
}
}
return append(service, append(postgresService)...)
}
The output of the postgresService variable looks like
[{CONTAINER_DB_NAME testdb nil} {CONTAINER_DB_USER &EnvVarSource{FieldRef:nil,ResourceFieldRef:nil,ConfigMapKeyRef:nil,SecretKeyRef:&SecretKeySelector{LocalObjectReference:LocalObjectReference{Name:secret,},Key:POSTGRES_USER,Optional:nil,},}} {CONTAINER_DB_PASSWORD &EnvVarSource{FieldRef:nil,ResourceFieldRef:nil,ConfigMapKeyRef:nil,SecretKeyRef:&SecretKeySelector{LocalObjectReference:LocalObjectReference{Name:secret,},Key:POSTGRES_PASSWORD,Optional:nil,},}}]
I have two problems here:
1- Is this the best way to change the default key names in my case?
2- If the variable postgresService contains more values but I just need the DATABASE_NAME and DATABASE_USER how can I delete the rest of the values from postgresService?

golang: declaring a camelcase in a struct declaration

I'm trying to read a yaml file via golang.
But the "matchLabels" sub-struct is not being recognized
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
labels:
app: test
spec:
replicas: 3
selector:
matchLabels:
app: web
struct
type myData struct {
Apivesion string `yaml:"apiVersion"`
Kind string
Metadata struct {
Name string
Labels struct {
App string
}
}
Spec struct {
Replicas int64
Selector struct {
Matchlabels struct {
App string
}
}
}
}
Expectation
&{apps/v1 Deployment {nginx-deploy {test}} {3 {{web}}}}
Result
&{apps/v1 Deployment {nginx-deploy {test}} {3 {{}}}}
Fix didn't work:
Matchlabels struct `yaml:"matchLabels"` {
Cerise Limón gave the answer in a comment:
Field tags follow the type:
Matchlabels struct { App string }
`yaml:"matchLabels"`
I don't think you implemented the suggested answer correctly, see where the tag is:
type myData struct {
Apivesion string `yaml:"apiVersion"`
Kind string
Metadata struct {
Name string
Labels struct {
App string
}
}
Spec struct {
Replicas int64
Selector struct {
Matchlabels struct {
App string
} `yaml:"matchLabels"`
}
}
}
See also: https://go.dev/play/p/yd9c-iBz2yL
type AutoGenerated struct {
APIVersion string `yaml:"apiVersion"`
Kind string `yaml:"kind"`
Metadata struct {
Name string `yaml:"name"`
Labels struct {
App string `yaml:"app"`
} `yaml:"labels"`
} `yaml:"metadata"`
Spec struct {
Replicas int `yaml:"replicas"`
Selector struct {
MatchLabels struct {
App string `yaml:"app"`
} `yaml:"matchLabels"`
} `yaml:"selector"`
} `yaml:"spec"`
}
You can use this tool, it is really helpful:
https://zhwt.github.io/yaml-to-go/

Ignored YAML tag

I have config.yml file:
vcenter:
connection: https
hostname: vcenter.mydomain.lan
username: readonlyauto#vsphere.local
password: mypasspord
port: 443
EsxiExcludeDatastores:
- datastore1
- datastore2
EsxiExcludeDatastores2:
datastores:
- datastore1
- datastore2
I'm trying to parse it with "gopkg.in/yaml.v2"
I created struct:
type FileConfig struct {
Vcenter struct {
ConnectionType string `yaml:"connection"`
Hostname string `yaml:"hostname"`
Username string `yaml:"username"`
Password string `yaml:"password"`
Port int `yaml:"port"`
} `yaml:"vcenter"`
EsxiExcludeDatastores struct {
Datastores []string `yaml:"EsxiExcludeDatastores"`
}
EsxiExcludeDatastores2 struct {
Datastores []string `yaml:"datastores"`
} `yaml:"EsxiExcludeDatastores2"`
}
var AppConfig FileConfig
After parsing, I print results:
fmt.Println("Num of EsxiExcludeDatastores.Datastores = ", len(AppConfig.EsxiExcludeDatastores.Datastores))
fmt.Println("Num of EsxiExcludeDatastores2.Datastores = ", len(AppConfig.EsxiExcludeDatastores2.Datastores))
Num of EsxiExcludeDatastores.Datastores = 0
Num of EsxiExcludeDatastores2.Datastores = 2
Can you help me, where I did mistake in EsxiExcludeDatastores struct? As you see, everything is fine with EsxiExcludeDatastores2, but EsxiExcludeDatastores is empty.
I tried to do this in different ways, but with no result ...
You're almost there.
To "promote" yaml struct tag(s) to the "parent" field, add:
EsxiExcludeDatastores struct {
Datastores []string `yaml:"EsxiExcludeDatastores"`
} `yaml:",inline"` // <- this
https://play.golang.org/p/S7QxGaspTyN
From the yaml.v2 docs, a struct tag that uses the inline flag does the following:
Inline the field, which must be a struct or a map, causing all of its
fields or keys to be processed as if they were part of the outer
struct. For maps, keys must not conflict with the yaml keys of other
struct fields.

Golang - Missing expression error on structs

type Old struct {
UserID int `json:"user_ID"`
Data struct {
Address string `json:"address"`
} `json:"old_data"`
}
type New struct {
UserID int `json:"userId"`
Data struct {
Address string `json:"address"`
} `json:"new_data"`
}
func (old Old) ToNew() New {
return New{
UserID: old.UserID,
Data: { // from here it says missing expression
Address: old.Data.Address,
},
}
}
What is "missing expression" error when using structs?
I am transforming old object to a new one. I minified them just to get straight to the point but the transformation is much more complex. The UserID field for example works great. But when I use struct (which intended to be a JSON object in the end) the Goland IDE screams "missing expression" and the compiler says "missing type in composite literal" on this line. What I am doing wrong? Maybe should I use something else instead of struct? Please help.
Data is an anonymous struct, so you need to write it like this:
type New struct {
UserID int `json:"userId"`
Data struct {
Address string `json:"address"`
} `json:"new_data"`
}
func (old Old) ToNew() New {
return New{
UserID: old.UserID,
Data: struct {
Address string `json:"address"`
}{
Address: old.Data.Address,
},
}
}
(playground link)
I think it'd be cleanest to create a named Address struct.
You're defining Data as an inline struct. When assigning values to it, you must first put the inline declaration:
func (old Old) ToNew() New {
return New{
UserID: old.UserID,
Data: struct {
Address string `json:"address"`
}{
Address: old.Data.Address,
},
}
}
Hence it is generally better to define a separate type for Data, just like User.

How to parameterize enumerator in rust?

I'm very new to Rust and faced the following simple problem
I have the following 2 enums:
enum SourceType{
File,
Network
}
enum SourceProperties{
FileProperties {
file_path: String
},
NetworkProperties {
ip: String
}
}
Now I'd like to have HashMap<SourceType, SourceProperties>, but in such an implementation there is a potential to have mapping File -> NetworkProperties which is not what's expected.
I was thinking about to parameterize enum SourceProperties<T> with SourceType somehow, but it does not seem to be possible. Is there a way to provide such typesafety guarantees?
UPD: The intention of having the enum SourceType is that the actual SourceType is a user input which will be decoded as a String value ("File", "Network"). So the workflow would look like this
"File" -> SourceType::File -> SourceProperties::NetworkProperties
You can simple use a hash set and an enum that encapsulates the properties, for latter matching of them:
use std::collections::HashSet;
#[derive(PartialEq, Eq, Hash)]
struct FileProperties {
file_path: String
}
#[derive(PartialEq, Eq, Hash)]
struct NetworkProperties {
ip: String
}
#[derive(PartialEq, Eq, Hash)]
enum Source {
File(FileProperties),
Network(NetworkProperties)
}
fn main() {
let mut set : HashSet<Source> = HashSet::new();
set.insert(Source::File(FileProperties{file_path: "foo.bar".to_string()}));
for e in set {
match e {
Source::File(properties) => { println!("{}", properties.file_path);}
Source::Network(properties) => { println!("{}", properties.ip);}
}
}
}
Playground

Resources