Skip to content

Commit

Permalink
Merge pull request #16 from kdeng3849/ENG-6658-user-defined-metadata
Browse files Browse the repository at this point in the history
ENG-6658 user defined metadata
  • Loading branch information
kqdeng committed Jul 24, 2020
2 parents e2b4d22 + 65f01e7 commit 013e57a
Show file tree
Hide file tree
Showing 7 changed files with 240 additions and 145 deletions.
5 changes: 4 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@ module github.com/packethost/hegel
go 1.13

require (
github.com/docker/go-metrics v0.0.1 // indirect
github.com/golang/protobuf v1.4.2
github.com/grpc-ecosystem/go-grpc-middleware v1.2.0
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
github.com/packethost/cacher v0.0.0-20200319200613-5dc1cac4fd33
github.com/packethost/pkg v0.0.0-20190715213007-7c3a64b4b5e3
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.5.1
github.com/tinkerbell/tink v0.0.0-20200708073808-997394055483
github.com/tinkerbell/tink v0.0.0-20200724140154-850584d46c8d
google.golang.org/grpc v1.29.1
)

replace github.com/tinkerbell/tink v0.0.0-20200710050004-a68bec0e8c1b => github.com/kdeng3849/tink v0.0.0-20200713034415-dd6d5ea8d040
66 changes: 66 additions & 0 deletions go.sum

Large diffs are not rendered by default.

40 changes: 27 additions & 13 deletions grpc_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"errors"
"fmt"
"io"
"math"
"net"
Expand Down Expand Up @@ -46,17 +47,8 @@ type exportedHardwareCacher struct {
// exportedHardwareTinkerbell is the structure in which hegel returns to clients using the new tinkerbell data model
// exposes only certain fields of the hardware data returned by tinkerbell
type exportedHardwareTinkerbell struct {
ID string `json:"id"`
Metadata metadata `json:"metadata"`
}

type metadata struct {
State string `json:"state"`
BondingMode int `json:"bonding_mode"`
Manufacturer interface{} `json:"manufacturer"`
Instance instance `json:"instance"`
Custom interface{} `json:"custom"`
Facility interface{} `json:"facility"`
ID string `json:"id"`
Metadata interface{} `json:"metadata"`
}

type instance struct {
Expand Down Expand Up @@ -218,6 +210,29 @@ func (eh *exportedHardwareCacher) UnmarshalJSON(b []byte) error {
return nil
}

// UnmarshalJSON implements the json.Unmarshaler interface for custom unmarshalling of exportedHardwareTinkerbell
// transforms the metadata from a string (as defined in the hardware returned by tink) into a map for cleaner printing
func (eh *exportedHardwareTinkerbell) UnmarshalJSON(b []byte) error {
type ehj exportedHardwareTinkerbell
var tmp ehj
err := json.Unmarshal(b, &tmp)
if err != nil {
return err
}

if md, ok := tmp.Metadata.(string); ok { // won't run block if unable to cast into string (including if nil)
metadata := make(map[string]interface{})
err = json.Unmarshal([]byte(md), &metadata) // metadata is now a map

if err != nil {
fmt.Println(err)
}
tmp.Metadata = metadata
}
*eh = exportedHardwareTinkerbell(tmp)
return nil
}

func (s *server) Get(ctx context.Context, in *hegel.GetRequest) (*hegel.GetResponse, error) {
p, ok := peer.FromContext(ctx)
if !ok {
Expand Down Expand Up @@ -264,7 +279,6 @@ func (s *server) Subscribe(in *hegel.SubscribeRequest, stream hegel.Hegel_Subscr
dataModelVersion := os.Getenv("DATA_MODEL_VERSION")
switch dataModelVersion {
case "1":
//tc := s.hardwareClient.(tink.HardwareServiceClient)
hw, err := s.hardwareClient.ByIP(stream.Context(), &tink.GetRequest{
Ip: ip,
})
Expand Down Expand Up @@ -403,7 +417,7 @@ func getByIP(ctx context.Context, s *server, userIP string) ([]byte, error) {
req := &tink.GetRequest{
Ip: userIP,
}
resp, err := s.hardwareClient.ByIP(ctx, req)
resp, err := s.hardwareClient.ByIP(ctx, req) // use wrapper?

if err != nil {
return nil, err
Expand Down
76 changes: 53 additions & 23 deletions grpc_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"encoding/json"
"os"
"testing"

"github.com/tinkerbell/tink/protos/packet"
)

func TestGetByIPCacher(t *testing.T) {
Expand Down Expand Up @@ -89,43 +91,64 @@ func TestGetByIPTinkerbell(t *testing.T) {
hw := exportedHardwareTinkerbell{}
err = json.Unmarshal(ehw, &hw)
if err != nil {
t.Fatal("Error in unmarshalling hardware", err)
t.Error("Error in unmarshalling hardware:", err)
}

if hw.ID != test.id {
t.Errorf("handler returned unexpected id: got %v want %v",
hw.ID, test.id)
}

if hw.Metadata == nil {
return
}

var metadata packet.Metadata
md, err := json.Marshal(hw.Metadata)
if err != nil {
t.Error("Error in unmarshalling hardware", err)
}
if hw.Metadata.State != test.state {
t.Fatalf("unexpected state, want: %v, got: %v\n", test.state, hw.Metadata.State)
err = json.Unmarshal(md, &metadata)
if err != nil {
t.Error("Error in unmarshalling hardware metadata", err)
}
if hw.Metadata.BondingMode != test.bondingMode {
t.Fatalf("unexpected bonding mode, want: %v, got: %v\n", test.bondingMode, hw.Metadata.BondingMode)

if metadata.State != test.state {
t.Fatalf("unexpected state, want: %v, got: %v\n", test.state, metadata.State)
}
if len(hw.Metadata.Instance.Storage.Disks) > 0 {
if hw.Metadata.Instance.Storage.Disks[0].Device != test.diskDevice {
t.Fatalf("unexpected disk device, want: %v, got: %v\n", test.diskDevice, hw.Metadata.Instance.Storage.Disks[0].Device)
if metadata.BondingMode != test.bondingMode {
t.Fatalf("unexpected bonding mode, want: %v, got: %v\n", test.bondingMode, metadata.BondingMode)
}
if len(metadata.Instance.Storage.Disks) > 0 {
if metadata.Instance.Storage.Disks[0].Device != test.diskDevice {
t.Fatalf("unexpected disk device, want: %v, got: %v\n", test.diskDevice, metadata.Instance.Storage.Disks[0].Device)
}
if hw.Metadata.Instance.Storage.Disks[0].WipeTable != test.wipeTable {
t.Fatalf("unexpected wipe table, want: %v, got: %v\n", test.wipeTable, hw.Metadata.Instance.Storage.Disks[0].WipeTable)
if metadata.Instance.Storage.Disks[0].WipeTable != test.wipeTable {
t.Fatalf("unexpected wipe table, want: %v, got: %v\n", test.wipeTable, metadata.Instance.Storage.Disks[0].WipeTable)
}
if int(hw.Metadata.Instance.Storage.Disks[0].Paritions[0].Size) != test.partitionSize {
t.Fatalf("unexpected partition size, want: %v, got: %v\n", test.partitionSize, hw.Metadata.Instance.Storage.Disks[0].Paritions[0].Size)
if metadata.Instance.Storage.Disks[0].Partitions[0].Size != test.partitionSize {
t.Fatalf("unexpected partition size, want: %v, got: %v\n", test.partitionSize, metadata.Instance.Storage.Disks[0].Partitions[0].Size)
}
}
if len(hw.Metadata.Instance.Storage.Filesystems) > 0 {
if hw.Metadata.Instance.Storage.Filesystems[0].Mount.Device != test.filesystemDevice {
t.Fatalf("unexpected filesystem mount device, want: %v, got: %v\n", test.filesystemDevice, hw.Metadata.Instance.Storage.Filesystems[0].Mount.Device)
if len(metadata.Instance.Storage.Filesystems) > 0 {
if metadata.Instance.Storage.Filesystems[0].Mount.Device != test.filesystemDevice {
t.Fatalf("unexpected filesystem mount device, want: %v, got: %v\n", test.filesystemDevice, metadata.Instance.Storage.Filesystems[0].Mount.Device)
}
if hw.Metadata.Instance.Storage.Filesystems[0].Mount.Format != test.filesystemFormat {
t.Fatalf("unexpected filesystem mount format, want: %v, got: %v\n", test.filesystemFormat, hw.Metadata.Instance.Storage.Filesystems[0].Mount.Format)
if metadata.Instance.Storage.Filesystems[0].Mount.Format != test.filesystemFormat {
t.Fatalf("unexpected filesystem mount format, want: %v, got: %v\n", test.filesystemFormat, metadata.Instance.Storage.Filesystems[0].Mount.Format)
}
}
if hw.Metadata.Instance.OS.OsSlug != test.osSlug {
t.Fatalf("unexpected os slug, want: %v, got: %v\n", test.osSlug, hw.Metadata.Instance.OS.OsSlug)
if metadata.Instance.OperatingSystemVersion.OsSlug != test.osSlug {
t.Fatalf("unexpected os slug, want: %v, got: %v\n", test.osSlug, metadata.Instance.OperatingSystemVersion.OsSlug)
}
if hw.Metadata.Facility.(map[string]interface{})["plan_slug"] != test.planSlug {
t.Fatalf("unexpected os slug, want: %v, got: %v\n", test.planSlug, hw.Metadata.Facility.(map[string]interface{})["plan_slug"])
if metadata.Facility.PlanSlug != test.planSlug {
t.Fatalf("unexpected os slug, want: %v, got: %v\n", test.planSlug, metadata.Facility.PlanSlug)
}
}
}

var cacherGrpcTests = map[string]struct {
id string
remote string
state string
facility string
Expand Down Expand Up @@ -232,12 +255,13 @@ var cacherGrpcTests = map[string]struct {
}

var tinkerbellGrpcTests = map[string]struct {
id string
remote string
state string
bondingMode int
bondingMode int64
diskDevice string
wipeTable bool
partitionSize int
partitionSize int64
filesystemDevice string
filesystemFormat string
osSlug string
Expand All @@ -246,6 +270,7 @@ var tinkerbellGrpcTests = map[string]struct {
error string
}{
"tinkerbell": {
id: "fde7c87c-d154-447e-9fce-7eb7bdec90c0",
remote: "192.168.1.5",
bondingMode: 5,
diskDevice: "/dev/sda",
Expand All @@ -257,4 +282,9 @@ var tinkerbellGrpcTests = map[string]struct {
planSlug: "c2.medium.x86",
json: tinkerbellDataModel,
},
"tinkerbell no metadata": {
id: "363115b0-f03d-4ce5-9a15-5514193d131a",
remote: "192.168.1.5",
json: tinkerbellNoMetadata,
},
}
2 changes: 1 addition & 1 deletion http_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func getMetadata(w http.ResponseWriter, r *http.Request) {
ehw, err := getByIP(context.Background(), hegelServer, userIP)
if err != nil {
metrics.Errors.WithLabelValues("metadata", "lookup").Inc()
logger.Info("Error in finding or exporting hardware ", err)
logger.Info("Error in finding or exporting hardware: ", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
Expand Down
28 changes: 25 additions & 3 deletions http_handlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"net/http/httptest"
"os"
"testing"

"github.com/tinkerbell/tink/protos/packet"
)

func TestGetMetadataCacher(t *testing.T) {
Expand Down Expand Up @@ -79,9 +81,24 @@ func TestGetMetadataTinkerbell(t *testing.T) {
t.Errorf("handler returned unexpected id: got %v want %v",
hw.ID, test.id)
}
if hw.Metadata.BondingMode != test.bondingMode {

if hw.Metadata == nil {
return
}

var metadata packet.Metadata
md, err := json.Marshal(hw.Metadata)
if err != nil {
t.Error("Error in marshalling hardware metadata", err)
}
err = json.Unmarshal(md, &metadata)
if err != nil {
t.Error("Error in unmarshalling hardware metadata", err)
}

if metadata.BondingMode != test.bondingMode {
t.Errorf("handler returned unexpected bonding mode: got %v want %v",
hw.Metadata.BondingMode, test.bondingMode)
metadata.BondingMode, test.bondingMode)
}
}
}
Expand All @@ -103,7 +120,7 @@ var cacherTests = map[string]struct {
var tinkerbellTests = map[string]struct {
id string
remote string
bondingMode int
bondingMode int64
json string
}{
"tinkerbell": {
Expand All @@ -112,4 +129,9 @@ var tinkerbellTests = map[string]struct {
bondingMode: 5,
json: tinkerbellDataModel,
},
"tinkerbell no metadata": {
id: "363115b0-f03d-4ce5-9a15-5514193d131a",
remote: "192.168.1.5",
json: tinkerbellNoMetadata,
},
}
Loading

0 comments on commit 013e57a

Please sign in to comment.