open-nomad/plugins/shared/structs/util.go
Mahmood Ali c5de71a424 Allow nullable fields in StatValues
In state values, we need to be able to distinguish between zero values
(e.g. `false`) and unset values (e.g. `nil`).

We can alternatively use protobuf `oneOf` and nested map to ensure
consistency of fields that are set together, but the golang
representation does not represent that well and introducing a mismatch
between representations.  Thus, I opted not to use it.
2018-11-14 14:41:19 -05:00

255 lines
5.1 KiB
Go

package structs
import (
"github.com/golang/protobuf/ptypes/wrappers"
"github.com/hashicorp/nomad/helper"
"github.com/hashicorp/nomad/plugins/shared/structs/proto"
)
func ConvertProtoAttribute(in *proto.Attribute) *Attribute {
out := &Attribute{
Unit: in.Unit,
}
switch in.Value.(type) {
case *proto.Attribute_BoolVal:
out.Bool = helper.BoolToPtr(in.GetBoolVal())
case *proto.Attribute_FloatVal:
out.Float = helper.Float64ToPtr(in.GetFloatVal())
case *proto.Attribute_IntVal:
out.Int = helper.Int64ToPtr(in.GetIntVal())
case *proto.Attribute_StringVal:
out.String = helper.StringToPtr(in.GetStringVal())
default:
}
return out
}
func ConvertProtoAttributeMap(in map[string]*proto.Attribute) map[string]*Attribute {
if in == nil {
return nil
}
out := make(map[string]*Attribute, len(in))
for k, a := range in {
out[k] = ConvertProtoAttribute(a)
}
return out
}
func ConvertStructsAttribute(in *Attribute) *proto.Attribute {
out := &proto.Attribute{
Unit: in.Unit,
}
if in.Int != nil {
out.Value = &proto.Attribute_IntVal{
IntVal: *in.Int,
}
} else if in.Float != nil {
out.Value = &proto.Attribute_FloatVal{
FloatVal: *in.Float,
}
} else if in.String != nil {
out.Value = &proto.Attribute_StringVal{
StringVal: *in.String,
}
} else if in.Bool != nil {
out.Value = &proto.Attribute_BoolVal{
BoolVal: *in.Bool,
}
}
return out
}
func ConvertStructAttributeMap(in map[string]*Attribute) map[string]*proto.Attribute {
if in == nil {
return nil
}
out := make(map[string]*proto.Attribute, len(in))
for k, a := range in {
out[k] = ConvertStructsAttribute(a)
}
return out
}
func Pow(a, b int64) int64 {
var p int64 = 1
for b > 0 {
if b&1 != 0 {
p *= a
}
b >>= 1
a *= a
}
return p
}
// CopyMapStringAttribute copies a map of string to Attribute
func CopyMapStringAttribute(in map[string]*Attribute) map[string]*Attribute {
if in == nil {
return nil
}
out := make(map[string]*Attribute, len(in))
for k, v := range in {
out[k] = v.Copy()
}
return out
}
// ConvertProtoStatObject converts between a proto and struct StatObject
func ConvertProtoStatObject(in *proto.StatObject) *StatObject {
if in == nil {
return nil
}
out := &StatObject{
Nested: make(map[string]*StatObject, len(in.Nested)),
Attributes: make(map[string]*StatValue, len(in.Attributes)),
}
for k, v := range in.Nested {
out.Nested[k] = ConvertProtoStatObject(v)
}
for k, v := range in.Attributes {
out.Attributes[k] = ConvertProtoStatValue(v)
}
return out
}
// ConvertProtoStatValue converts between a proto and struct StatValue
func ConvertProtoStatValue(in *proto.StatValue) *StatValue {
if in == nil {
return nil
}
return &StatValue{
FloatNumeratorVal: unwrapDouble(in.FloatNumeratorVal),
FloatDenominatorVal: unwrapDouble(in.FloatDenominatorVal),
IntNumeratorVal: unwrapInt64(in.IntNumeratorVal),
IntDenominatorVal: unwrapInt64(in.IntDenominatorVal),
StringVal: unwrapString(in.StringVal),
BoolVal: unwrapBool(in.BoolVal),
Unit: in.Unit,
Desc: in.Desc,
}
}
// ConvertStructStatObject converts between a struct and proto StatObject
func ConvertStructStatObject(in *StatObject) *proto.StatObject {
if in == nil {
return nil
}
out := &proto.StatObject{
Nested: make(map[string]*proto.StatObject, len(in.Nested)),
Attributes: make(map[string]*proto.StatValue, len(in.Attributes)),
}
for k, v := range in.Nested {
out.Nested[k] = ConvertStructStatObject(v)
}
for k, v := range in.Attributes {
out.Attributes[k] = ConvertStructStatValue(v)
}
return out
}
// ConvertStructStatValue converts between a struct and proto StatValue
func ConvertStructStatValue(in *StatValue) *proto.StatValue {
if in == nil {
return nil
}
return &proto.StatValue{
FloatNumeratorVal: wrapDouble(in.FloatNumeratorVal),
FloatDenominatorVal: wrapDouble(in.FloatDenominatorVal),
IntNumeratorVal: wrapInt64(in.IntNumeratorVal),
IntDenominatorVal: wrapInt64(in.IntDenominatorVal),
StringVal: wrapString(in.StringVal),
BoolVal: wrapBool(in.BoolVal),
Unit: in.Unit,
Desc: in.Desc,
}
}
// Helper functions for proto wrapping
func unwrapDouble(w *wrappers.DoubleValue) *float64 {
if w == nil {
return nil
}
v := w.Value
return &v
}
func wrapDouble(v *float64) *wrappers.DoubleValue {
if v == nil {
return nil
}
return &wrappers.DoubleValue{Value: *v}
}
func unwrapInt64(w *wrappers.Int64Value) *int64 {
if w == nil {
return nil
}
v := w.Value
return &v
}
func wrapInt64(v *int64) *wrappers.Int64Value {
if v == nil {
return nil
}
return &wrappers.Int64Value{Value: *v}
}
func unwrapString(w *wrappers.StringValue) *string {
if w == nil {
return nil
}
v := w.Value
return &v
}
func wrapString(v *string) *wrappers.StringValue {
if v == nil {
return nil
}
return &wrappers.StringValue{Value: *v}
}
func unwrapBool(w *wrappers.BoolValue) *bool {
if w == nil {
return nil
}
v := w.Value
return &v
}
func wrapBool(v *bool) *wrappers.BoolValue {
if v == nil {
return nil
}
return &wrappers.BoolValue{Value: *v}
}