diff --git a/go.sum b/go.sum index 8fe7f93a..31a005f9 100644 --- a/go.sum +++ b/go.sum @@ -54,7 +54,6 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2-0.20190318194812-d3c38a4eb497/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= @@ -118,7 +117,6 @@ github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2t github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is= github.com/lestrrat-go/strftime v1.0.1 h1:o7qz5pmLzPDLyGW4lG6JvTKPUfTFXwe+vOamIYWtnVU= github.com/lestrrat-go/strftime v1.0.1/go.mod h1:E1nN3pCbtMSu1yjSVeyuRFVm/U0xoR76fd03sz+Qz4g= -github.com/lib/pq v0.0.0-20180523175426-90697d60dd84/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.1-0.20191011153232-f91d3411e481/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -145,8 +143,6 @@ github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uY github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/packethost/cacher v0.0.0-20200319200613-5dc1cac4fd33 h1:UdZrpbRKPsvI3gfTRR15e6DDtMJD1jX/kQedHRUO5Vg= -github.com/packethost/cacher v0.0.0-20200319200613-5dc1cac4fd33/go.mod h1:3y8RWuSOmBK0CfH/6v7KwNei2hCbgZ3QSyeltn8695A= github.com/packethost/cacher v0.0.0-20200825140532-0b62e6726807 h1:6eazj7oiSs6rn/siUM27SVzanwE/cAs46i5u1XE1Q88= github.com/packethost/cacher v0.0.0-20200825140532-0b62e6726807/go.mod h1:D48hh9rF21NuFQ27IjS+3BPUUiXCIROENcEAQGk0p9Q= github.com/packethost/packngo v0.1.1-0.20180510203711-dff6ec250ba6/go.mod h1:otzZQXgoO96RTzDB/Hycg0qZcXZsWJGJRSXbmEIJ+4M= @@ -166,31 +162,23 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.9.0-pre1.0.20180602003245-a62824bd1b05/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= -github.com/prometheus/client_golang v1.5.1 h1:bdHYieyGlH+6OLEk2YQha8THib30KP0/yD0YH9m6xcA= -github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.6.0 h1:YVPodQOcK15POxhgARIvnDRVpLcuK8mglnMrWfyrw6A= github.com/prometheus/client_golang v1.6.0/go.mod h1:ZLOG9ck3JLRdB5MgO8f+lLTe83AXG6ro35rLTxvnIl4= -github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20180518154759-7600349dcfe1/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/procfs v0.0.0-20180601124529-94663424ae5a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.0.11 h1:DhHlBtkHWPYi8O2y31JkK0TF+DGM+51OopZjH/Ia5qI= github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= @@ -270,8 +258,6 @@ golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82 h1:ywK/j/KkyTHcdyYSZNXGjMwgmDSfjglYZ3vStQ/gSCU= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -295,7 +281,6 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IV golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180531194445-4065a77fc542/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190708153700-3bdd9d9f5532/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= @@ -303,7 +288,6 @@ google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884 h1:fiNLklpBwWK1mth google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= diff --git a/http_server.go b/http_server.go index 7818d208..da06084b 100644 --- a/http_server.go +++ b/http_server.go @@ -8,7 +8,7 @@ import ( "github.com/prometheus/client_golang/prometheus/promhttp" ) -func ServeHTTP() { +func ServeHTTP(customEndpoints map[string]string) { mux := &http.ServeMux{} mux.Handle("/metrics", promhttp.Handler()) mux.HandleFunc("/_packet/healthcheck", healthCheckHandler) @@ -18,7 +18,7 @@ func ServeHTTP() { buildSubscriberHandlers(hegelServer) - err := registerCustomEndpoints(mux) + err := registerCustomEndpoints(mux, customEndpoints) if err != nil { logger.Fatal(err, "could not register custom endpoints") } @@ -30,8 +30,7 @@ func ServeHTTP() { go func() { err := http.ListenAndServe(fmt.Sprintf(":%d", *metricsPort), nil) if err != nil { - logger.Error(err, "failed to serve http") - panic(err) + logger.Fatal(err, "failed to serve http") } }() } diff --git a/http_server_test.go b/http_server_test.go index 3b03820f..afca1aeb 100644 --- a/http_server_test.go +++ b/http_server_test.go @@ -12,7 +12,6 @@ import ( "testing" "github.com/packethost/hegel/xff" - "github.com/tinkerbell/tink/protos/packet" ) // TestTrustedProxies tests if the actual remote user IP is extracted correctly from the X-FORWARDED-FOR header according to the list of trusted proxies provided @@ -60,46 +59,43 @@ func TestTrustedProxies(t *testing.T) { func TestGetMetadataCacher(t *testing.T) { for name, test := range cacherTests { - t.Log(name) - hegelServer.hardwareClient = hardwareGetterMock{test.json} - - dataModelVersion := os.Getenv("DATA_MODEL_VERSION") - defer os.Setenv("DATA_MODEL_VERSION", dataModelVersion) - os.Unsetenv("DATA_MODEL_VERSION") + t.Run(name, func(t *testing.T) { + hegelServer.hardwareClient = hardwareGetterMock{test.json} - customEndpoints := os.Getenv("CUSTOM_ENDPOINTS") - defer os.Setenv("CUSTOM_ENDPOINTS", customEndpoints) - os.Unsetenv("CUSTOM_ENDPOINTS") + dataModelVersion := os.Getenv("DATA_MODEL_VERSION") + defer os.Setenv("DATA_MODEL_VERSION", dataModelVersion) + os.Unsetenv("DATA_MODEL_VERSION") - req, err := http.NewRequest("GET", "/metadata", nil) - if err != nil { - t.Fatal(err) - } - req.RemoteAddr = mockUserIP - resp := httptest.NewRecorder() - http.HandleFunc("/metadata", getMetadata("")) // filter not used in cacher mode + req, err := http.NewRequest("GET", "/metadata", nil) + if err != nil { + t.Fatal(err) + } + req.RemoteAddr = mockUserIP + resp := httptest.NewRecorder() + http.HandleFunc("/metadata", getMetadata("")) // filter not used in cacher mode - http.DefaultServeMux.ServeHTTP(resp, req) + http.DefaultServeMux.ServeHTTP(resp, req) - if status := resp.Code; status != http.StatusOK { - t.Errorf("handler returned wrong status code: got %v want %v", - status, http.StatusOK) - } + if status := resp.Code; status != http.StatusOK { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusOK) + } - hw := exportedHardwareCacher{} - err = json.Unmarshal(resp.Body.Bytes(), &hw) - if err != nil { - t.Error("Error in unmarshalling hardware:", err) - } + hw := exportedHardwareCacher{} + err = json.Unmarshal(resp.Body.Bytes(), &hw) + if err != nil { + 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.PlanSlug != test.planSlug { - t.Errorf("handler returned unexpected plan slug: got %v want %v", - hw.PlanSlug, test.planSlug) - } + if hw.ID != test.id { + t.Errorf("handler returned unexpected id: got %v want %v", + hw.ID, test.id) + } + if hw.PlanSlug != test.planSlug { + t.Errorf("handler returned unexpected plan slug: got %v want %v", + hw.PlanSlug, test.planSlug) + } + }) } } @@ -109,49 +105,50 @@ func TestGetMetadataTinkerbell(t *testing.T) { defer os.Setenv("DATA_MODEL_VERSION", dataModelVersion) os.Setenv("DATA_MODEL_VERSION", "1") - customEndpoints := os.Getenv("CUSTOM_ENDPOINTS") - defer os.Setenv("CUSTOM_ENDPOINTS", customEndpoints) - os.Unsetenv("CUSTOM_ENDPOINTS") - + defaultCustomEndpoints, err := parseCustomEndpoints("") + if err != nil { + t.Error(err) + } for name, test := range tinkerbellTests { - t.Log(name) - hegelServer.hardwareClient = hardwareGetterMock{test.json} + t.Run(name, func(t *testing.T) { + hegelServer.hardwareClient = hardwareGetterMock{test.json} - mux := &http.ServeMux{} + mux := &http.ServeMux{} - err := registerCustomEndpoints(mux) - if err != nil { - t.Fatal("Error registering custom endpoints", err) - } + err := registerCustomEndpoints(mux, defaultCustomEndpoints) + if err != nil { + t.Fatal("Error registering custom endpoints", err) + } - req, err := http.NewRequest("GET", "/metadata", nil) - if err != nil { - t.Fatal(err) - } - req.RemoteAddr = mockUserIP - resp := httptest.NewRecorder() + req, err := http.NewRequest("GET", "/metadata", nil) + if err != nil { + t.Fatal(err) + } + req.RemoteAddr = mockUserIP + resp := httptest.NewRecorder() - mux.ServeHTTP(resp, req) + mux.ServeHTTP(resp, req) - if status := resp.Code; status != http.StatusOK { - t.Errorf("handler returned wrong status code: got %v want %v", - status, http.StatusOK) - } + if status := resp.Code; status != http.StatusOK { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusOK) + } - if resp.Body.Bytes() == nil { - return - } + if resp.Body.Bytes() == nil { + return + } - var metadata packet.Metadata - err = json.Unmarshal(resp.Body.Bytes(), &metadata) - if err != nil { - t.Error("Error in unmarshalling hardware metadata:", err) - } + var metadata map[string]interface{} + err = json.Unmarshal(resp.Body.Bytes(), &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", - metadata.BondingMode, test.bondingMode) - } + if metadata["crypted_root_password"].(string) != test.crypted_root_password { + t.Errorf("handler returned unexpected crypted_root_password: got %v want %v", + metadata["crypted_root_password"], test.crypted_root_password) + } + }) } } @@ -161,39 +158,41 @@ func TestGetMetadataTinkerbellKant(t *testing.T) { defer os.Setenv("DATA_MODEL_VERSION", dataModelVersion) os.Setenv("DATA_MODEL_VERSION", "1") - customEndpoints := os.Getenv("CUSTOM_ENDPOINTS") - defer os.Setenv("CUSTOM_ENDPOINTS", customEndpoints) - os.Setenv("CUSTOM_ENDPOINTS", `{"/metadata":".metadata.instance","/components":".metadata.components","/userdata":".metadata.userdata"}`) - + customEndpoints := map[string]string{ + "/metadata": ".metadata.instance", + "/components": ".metadata.components", + "/userdata": ".metadata.userdata", + } for name, test := range tinkerbellKantTests { - t.Log(name) - hegelServer.hardwareClient = hardwareGetterMock{test.json} + t.Run(name, func(t *testing.T) { + hegelServer.hardwareClient = hardwareGetterMock{test.json} - mux := &http.ServeMux{} + mux := &http.ServeMux{} - err := registerCustomEndpoints(mux) - if err != nil { - t.Fatal("Error registering custom endpoints", err) - } + err := registerCustomEndpoints(mux, customEndpoints) + if err != nil { + t.Fatal("Error registering custom endpoints", err) + } - req, err := http.NewRequest("GET", test.url, nil) - if err != nil { - t.Fatal(err) - } - req.RemoteAddr = mockUserIP - resp := httptest.NewRecorder() + req, err := http.NewRequest("GET", test.url, nil) + if err != nil { + t.Fatal(err) + } + req.RemoteAddr = mockUserIP + resp := httptest.NewRecorder() - mux.ServeHTTP(resp, req) + mux.ServeHTTP(resp, req) - if status := resp.Code; status != http.StatusOK { - t.Errorf("handler returned wrong status code: got %v want %v", - status, http.StatusOK) - } + if status := resp.Code; status != http.StatusOK { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusOK) + } - if resp.Body.String() != test.response { - t.Errorf("handler returned with unexpected body: got %v want %v", - resp.Body.String(), test.response) - } + if resp.Body.String() != test.response { + t.Errorf("handler returned with unexpected body: got %v want %v", + resp.Body.String(), test.response) + } + }) } } @@ -202,47 +201,50 @@ func TestRegisterEndpoints(t *testing.T) { defer os.Setenv("DATA_MODEL_VERSION", dataModelVersion) os.Setenv("DATA_MODEL_VERSION", "1") - customEndpoints := os.Getenv("CUSTOM_ENDPOINTS") - defer os.Setenv("CUSTOM_ENDPOINTS", customEndpoints) - for name, test := range registerEndpointTests { - t.Log(name) - hegelServer.hardwareClient = hardwareGetterMock{test.json} + t.Run(name, func(t *testing.T) { + hegelServer.hardwareClient = hardwareGetterMock{test.json} - os.Unsetenv("CUSTOM_ENDPOINTS") - if test.customEndpoints != "" { - os.Setenv("CUSTOM_ENDPOINTS", test.customEndpoints) - } + customEndpoints, err := parseCustomEndpoints(test.customEndpoints) + if test.error != "" { + if err == nil { + t.Fatalf("parseCustomEndpoints should have returned error: %v", test.error) + } else if err.Error() != test.error { + t.Fatalf("parseCustomEndpoints returned wrong error: got %v want %v", err, test.error) + } + return + } - mux := &http.ServeMux{} + mux := &http.ServeMux{} - err := registerCustomEndpoints(mux) - if test.error != "" { - if err == nil { - t.Fatalf("registerCustomEndpoints should have returned error: %v", test.error) - } else if err.Error() != test.error { - t.Fatalf("registerCustomEndpoints returned wrong error: got %v want %v", err, test.error) + err = registerCustomEndpoints(mux, customEndpoints) + if test.error != "" { + if err == nil { + t.Fatalf("registerCustomEndpoints should have returned error: %v", test.error) + } else if err.Error() != test.error { + t.Fatalf("registerCustomEndpoints returned wrong error: got %v want %v", err, test.error) + } } - } - req, err := http.NewRequest("GET", test.url, nil) - if err != nil { - t.Fatal(err) - } - req.RemoteAddr = mockUserIP - resp := httptest.NewRecorder() + req, err := http.NewRequest("GET", test.url, nil) + if err != nil { + t.Fatal(err) + } + req.RemoteAddr = mockUserIP + resp := httptest.NewRecorder() - mux.ServeHTTP(resp, req) + mux.ServeHTTP(resp, req) - if status := resp.Code; status != test.status { - t.Errorf("handler returned wrong status code: got %v want %v", - status, test.status) - } + if status := resp.Code; status != test.status { + t.Errorf("handler returned wrong status code: got %v want %v", + status, test.status) + } - t.Log("response:", resp.Body.String()) // logging response instead of explicitly checking content - if resp.Body.String() == "" && !test.expectResponseEmpty { - t.Errorf("handler should have returned a non-empty response") - } + t.Log("response:", resp.Body.String()) // logging response instead of explicitly checking content + if resp.Body.String() == "" && !test.expectResponseEmpty { + t.Errorf("handler should have returned a non-empty response") + } + }) } } @@ -316,24 +318,24 @@ func TestEC2FiltersMap(t *testing.T) { if basePath == "" { // ignore the `"": []` entry continue } - t.Log("base path:", basePath) - - hw := `{"metadata":{"instance":{"spot":{}}}}` // to make sure the 'spot' metadata item will be included - query := strings.TrimSuffix(basePath, "/") - dirListFilter := ec2Filters[query] // get the directory-list filter - itemsFromFilter, err := filterMetadata([]byte(hw), dirListFilter) - if err != nil { - t.Errorf("failed to filter metadata: %s", err) - } + t.Run(basePath, func(t *testing.T) { + hw := `{"metadata":{"instance":{"spot":{}}}}` // to make sure the 'spot' metadata item will be included + query := strings.TrimSuffix(basePath, "/") + dirListFilter := ec2Filters[query] // get the directory-list filter + itemsFromFilter, err := filterMetadata([]byte(hw), dirListFilter) + if err != nil { + t.Errorf("failed to filter metadata: %s", err) + } - sort.Strings(metadataItems) - itemsFromQueries := strings.Join(metadataItems, "\n") + sort.Strings(metadataItems) + itemsFromQueries := strings.Join(metadataItems, "\n") - if string(itemsFromFilter) != itemsFromQueries { - t.Error("directory-list does not match the actual queries") - t.Errorf("from filter: %s", itemsFromFilter) - t.Errorf("from queries: %s", itemsFromQueries) - } + if string(itemsFromFilter) != itemsFromQueries { + t.Error("directory-list does not match the actual queries") + t.Errorf("from filter: %s", itemsFromFilter) + t.Errorf("from queries: %s", itemsFromQueries) + } + }) } } @@ -467,14 +469,14 @@ var cacherTests = map[string]struct { // test cases for TestGetMetadataTinkerbell var tinkerbellTests = map[string]struct { - id string - bondingMode int64 - json string + id string + crypted_root_password string + json string }{ "tinkerbell": { - id: "fde7c87c-d154-447e-9fce-7eb7bdec90c0", - bondingMode: 5, - json: tinkerbellDataModel, + id: "fde7c87c-d154-447e-9fce-7eb7bdec90c0", + crypted_root_password: "redacted/", + json: tinkerbellDataModel, }, "tinkerbell no metadata": { id: "363115b0-f03d-4ce5-9a15-5514193d131a", diff --git a/main.go b/main.go index b6b7c7c5..7bd7ed82 100644 --- a/main.go +++ b/main.go @@ -93,6 +93,8 @@ func (hg hardwareGetterTinkerbell) Watch(ctx context.Context, in getRequest, opt return w, nil } +const defaultCustomEndpoints = `{"/metadata":".metadata.instance"}` + var ( facility = flag.String("facility", env.Get("HEGEL_FACILITY", "onprem"), "The facility we are running in (mostly to connect to cacher)") @@ -104,7 +106,6 @@ var ( "Whether we should use tls or not (should be disabled for traefik)") metricsPort = flag.Int("http_port", env.Int("HEGEL_HTTP_PORT", 50061), "Port to liten on http") - customEndpoints string gitRev string = "undefind" gitRevJSON []byte StartTime = time.Now() @@ -135,8 +136,7 @@ func main() { if *useTLS { creds, err := credentials.NewServerTLSFromFile(*tlsCertPath, *tlsKeyPath) if err != nil { - logger.Error(err, "failed to initialize server credentials") - panic(err) + logger.Fatal(err, "failed to initialize server credentials") } serverOpts = append(serverOpts, grpc.Creds(creds)) } @@ -220,13 +220,17 @@ func main() { lis, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) if err != nil { err = errors.Wrap(err, "failed to listen") - logger.Error(err) - panic(err) + logger.Fatal(err) } // Register grpc prometheus server grpc_prometheus.Register(grpcServer) - ServeHTTP() + + endpoints, err := parseCustomEndpoints(env.Get("CUSTOM_ENDPOINTS")) + if err != nil { + logger.Fatal(err) + } + ServeHTTP(endpoints) metrics.State.Set(metrics.Ready) //Serving GRPC @@ -237,17 +241,25 @@ func main() { } } -func registerCustomEndpoints(mux *http.ServeMux) error { - customEndpoints = env.Get("CUSTOM_ENDPOINTS", `{"/metadata":".metadata"}`) - if mux == nil { - mux = http.DefaultServeMux +func parseCustomEndpoints(customEndpoints string) (map[string]string, error) { + if customEndpoints == "" { + customEndpoints = defaultCustomEndpoints } endpoints := make(map[string]string) err := json.Unmarshal([]byte(customEndpoints), &endpoints) if err != nil { - return errors.Wrap(err, "error in parsing custom endpoints") + err = errors.Wrap(err, "error in parsing custom endpoints") + return nil, err } + return endpoints, nil +} + +func registerCustomEndpoints(mux *http.ServeMux, endpoints map[string]string) error { + if mux == nil { + mux = http.DefaultServeMux + } + for endpoint, filter := range endpoints { mux.HandleFunc(endpoint, getMetadata(filter)) } diff --git a/mock.go b/mock.go index 696e9242..6217fc6b 100644 --- a/mock.go +++ b/mock.go @@ -58,328 +58,334 @@ func (hg hardwareGetterMock) Watch(ctx context.Context, in getRequest, opts ...g const ( mockUserIP = "192.168.1.5" // value is completely arbitrary, as long as it's an IP to be parsed by getIPFromRequest (could even be 0.0.0.0) cacherDataModel = ` - { - "id": "8978e7d4-1a55-4845-8a66-a5259236b104", - "arch": "x86_64", - "name": "node-name", - "state": "provisioning", - "allow_pxe": true, - "allow_workflow": true, - "plan_slug": "t1.small.x86", - "facility_code": "onprem", - "efi_boot": false, - "instance": { - "storage": { - "disks": [ - { - "device": "/dev/sda", - "wipeTable": true, - "partitions": [ - { - "size": 4096, - "label": "BIOS", - "number": 1 - }, - { - "size": "3993600", - "label": "SWAP", - "number": 2 - }, - { - "size": 0, - "label": "ROOT", - "number": 3 - } - ] - } - ], - "filesystems": [ - { - "mount": { - "point": "/", - "create": { - "options": ["-L", "ROOT"] - }, - "device": "/dev/sda3", - "format": "ext4" - } - }, - { - "mount": { - "point": "none", - "create": { - "options": ["-L", "SWAP"] - }, - "device": "/dev/sda2", - "format": "swap" - } - } - ] - }, - "crypted_root_password": "$6$qViImWbWFfH/a4pq$s1bpFFXMpQj1eQbHWsruLy6/", - "operating_system_version": { - "distro": "ubuntu", - "version": "16.04", - "os_slug": "ubuntu_16_04" - } - }, - "ip_addresses": [ - { - "cidr": 29, - "public": false, - "address": "192.168.1.5", - "enabled": true, - "gateway": "192.168.1.1", - "netmask": "255.255.255.248", - "network": "192.168.1.0", - "address_family": 4 - } - ], - "network_ports": [ - { - "data": { - "mac": "98:03:9b:48:de:bc" - }, - "name": "eth0", - "type": "data" - } - ] - } +{ + "allow_pxe": true, + "allow_workflow": true, + "arch": "x86_64", + "efi_boot": false, + "facility_code": "onprem", + "id": "8978e7d4-1a55-4845-8a66-a5259236b104", + "instance": { + "crypted_root_password": "$6$qViImWbWFfH/a4pq$s1bpFFXMpQj1eQbHWsruLy6/", + "operating_system_version": { + "distro": "ubuntu", + "os_slug": "ubuntu_16_04", + "version": "16.04" + }, + "storage": { + "disks": [ + { + "device": "/dev/sda", + "partitions": [ + { + "label": "BIOS", + "number": 1, + "size": 4096 + }, + { + "label": "SWAP", + "number": 2, + "size": "3993600" + }, + { + "label": "ROOT", + "number": 3, + "size": 0 + } + ], + "wipeTable": true + } + ], + "filesystems": [ + { + "mount": { + "create": { + "options": [ + "-L", + "ROOT" + ] + }, + "device": "/dev/sda3", + "format": "ext4", + "point": "/" + } + }, + { + "mount": { + "create": { + "options": [ + "-L", + "SWAP" + ] + }, + "device": "/dev/sda2", + "format": "swap", + "point": "none" + } + } + ] + } + }, + "ip_addresses": [ + { + "address": "192.168.1.5", + "address_family": 4, + "cidr": 29, + "enabled": true, + "gateway": "192.168.1.1", + "netmask": "255.255.255.248", + "network": "192.168.1.0", + "public": false + } + ], + "name": "node-name", + "network_ports": [ + { + "data": { + "mac": "98:03:9b:48:de:bc" + }, + "name": "eth0", + "type": "data" + } + ], + "plan_slug": "t1.small.x86", + "state": "provisioning" +} ` cacherPartitionSizeInt = ` - { - "id": "8978e7d4-1a55-4845-8a66-a5259236b104", - "instance": { - "storage": { - "disks": [ - { - "partitions": [ - { - "size": 4096, - "label": "BIOS", - "number": 1 - } - ] - } - ] +{ + "id": "8978e7d4-1a55-4845-8a66-a5259236b104", + "instance": { + "storage": { + "disks": [ + { + "partitions": [ + { + "label": "BIOS", + "number": 1, + "size": 4096 + } + ] } - } - } + ] + } + } +} ` cacherPartitionSizeString = ` - { - "id": "8978e7d4-1a55-4845-8a66-a5259236b104", - "instance": { - "storage": { - "disks": [ - { - "partitions": [ - { - "size": "3333", - "label": "BIOS", - "number": 1 - } - ] - } - ] +{ + "id": "8978e7d4-1a55-4845-8a66-a5259236b104", + "instance": { + "storage": { + "disks": [ + { + "partitions": [ + { + "label": "BIOS", + "number": 1, + "size": "3333" + } + ] } - } - } + ] + } + } +} ` cacherPartitionSizeBLower = ` - { - "id": "8978e7d4-1a55-4845-8a66-a5259236b104", - "instance": { - "storage": { - "disks": [ - { - "partitions": [ - { - "size": "1000000b", - "label": "BIOS", - "number": 1 - } - ] - } - ] +{ + "id": "8978e7d4-1a55-4845-8a66-a5259236b104", + "instance": { + "storage": { + "disks": [ + { + "partitions": [ + { + "label": "BIOS", + "number": 1, + "size": "1000000b" + } + ] } - } - } + ] + } + } +} ` tinkerbellDataModel = ` - { - "network":{ - "interfaces":[ - { - "dhcp":{ - "mac":"ec:0d:9a:c0:01:0c", - "hostname":"server001", - "lease_time":86400, - "arch":"x86_64", - "ip":{ - "address":"192.168.1.5", - "netmask":"255.255.255.248", - "gateway":"192.168.1.1" - } - }, - "netboot":{ - "allow_pxe":true, - "allow_workflow":true, - "ipxe":{ - "url":"http://url/menu.ipxe", - "contents":"#!ipxe" - }, - "osie":{ - "kernel":"vmlinuz-x86_64" - } - } - } - ] - }, - "id":"fde7c87c-d154-447e-9fce-7eb7bdec90c0", - "metadata":"{\"components\":{\"id\":\"bc9ce39b-7f18-425b-bc7b-067914fa9786\",\"type\":\"DiskComponent\"},\"userdata\":\"#!/bin/bash\\necho \\\"Hello world!\\\"\",\"bonding_mode\":5,\"custom\":{\"preinstalled_operating_system_version\":{},\"private_subnets\":[]},\"facility\":{\"facility_code\":\"ewr1\",\"plan_slug\":\"c2.medium.x86\",\"plan_version_slug\":\"\"},\"instance\":{\"crypted_root_password\":\"redacted/\",\"operating_system_version\":{\"distro\":\"ubuntu\",\"os_slug\":\"ubuntu_18_04\",\"version\":\"18.04\"},\"storage\":{\"disks\":[{\"device\":\"/dev/sda\",\"partitions\":[{\"label\":\"BIOS\",\"number\":1,\"size\":4096},{\"label\":\"SWAP\",\"number\":2,\"size\":3993600},{\"label\":\"ROOT\",\"number\":3,\"size\":0}],\"wipe_table\":true}],\"filesystems\":[{\"mount\":{\"create\":{\"options\":[\"-L\",\"ROOT\"]},\"device\":\"/dev/sda3\",\"format\":\"ext4\",\"point\":\"/\"}},{\"mount\":{\"create\":{\"options\":[\"-L\",\"SWAP\"]},\"device\":\"/dev/sda2\",\"format\":\"swap\",\"point\":\"none\"}}]}},\"manufacturer\":{\"id\":\"\",\"slug\":\"\"},\"state\":\"\"}" - } +{ + "id": "fde7c87c-d154-447e-9fce-7eb7bdec90c0", + "metadata": "{\"components\":{\"id\":\"bc9ce39b-7f18-425b-bc7b-067914fa9786\",\"type\":\"DiskComponent\"},\"userdata\":\"#!/bin/bash\\necho \\\"Hello world!\\\"\",\"bonding_mode\":5,\"custom\":{\"preinstalled_operating_system_version\":{},\"private_subnets\":[]},\"facility\":{\"facility_code\":\"ewr1\",\"plan_slug\":\"c2.medium.x86\",\"plan_version_slug\":\"\"},\"instance\":{\"crypted_root_password\":\"redacted/\",\"operating_system_version\":{\"distro\":\"ubuntu\",\"os_slug\":\"ubuntu_18_04\",\"version\":\"18.04\"},\"storage\":{\"disks\":[{\"device\":\"/dev/sda\",\"partitions\":[{\"label\":\"BIOS\",\"number\":1,\"size\":4096},{\"label\":\"SWAP\",\"number\":2,\"size\":3993600},{\"label\":\"ROOT\",\"number\":3,\"size\":0}],\"wipe_table\":true}],\"filesystems\":[{\"mount\":{\"create\":{\"options\":[\"-L\",\"ROOT\"]},\"device\":\"/dev/sda3\",\"format\":\"ext4\",\"point\":\"/\"}},{\"mount\":{\"create\":{\"options\":[\"-L\",\"SWAP\"]},\"device\":\"/dev/sda2\",\"format\":\"swap\",\"point\":\"none\"}}]}},\"manufacturer\":{\"id\":\"\",\"slug\":\"\"},\"state\":\"\"}", + "network": { + "interfaces": [ + { + "dhcp": { + "arch": "x86_64", + "hostname": "server001", + "ip": { + "address": "192.168.1.5", + "gateway": "192.168.1.1", + "netmask": "255.255.255.248" + }, + "lease_time": 86400, + "mac": "ec:0d:9a:c0:01:0c" + }, + "netboot": { + "allow_pxe": true, + "allow_workflow": true, + "ipxe": { + "contents": "#!ipxe", + "url": "http://url/menu.ipxe" + }, + "osie": { + "kernel": "vmlinuz-x86_64" + } + } + } + ] + } +} ` tinkerbellNoMetadata = ` - { - "network":{ - "interfaces":[ - { - "dhcp":{ - "mac":"ec:0d:9a:c0:01:0c", - "hostname":"server001", - "lease_time":86400, - "arch":"x86_64", - "ip":{ - "address":"192.168.1.5", - "netmask":"255.255.255.248", - "gateway":"192.168.1.1" - } - }, - "netboot":{ - "allow_pxe":true, - "allow_workflow":true, - "ipxe":{ - "url":"http://url/menu.ipxe", - "contents":"#!ipxe" - }, - "osie":{ - "kernel":"vmlinuz-x86_64" - } - } - } - ] - }, - "id":"363115b0-f03d-4ce5-9a15-5514193d131a" - } +{ + "id": "363115b0-f03d-4ce5-9a15-5514193d131a", + "network": { + "interfaces": [ + { + "dhcp": { + "arch": "x86_64", + "hostname": "server001", + "ip": { + "address": "192.168.1.5", + "gateway": "192.168.1.1", + "netmask": "255.255.255.248" + }, + "lease_time": 86400, + "mac": "ec:0d:9a:c0:01:0c" + }, + "netboot": { + "allow_pxe": true, + "allow_workflow": true, + "ipxe": { + "contents": "#!ipxe", + "url": "http://url/menu.ipxe" + }, + "osie": { + "kernel": "vmlinuz-x86_64" + } + } + } + ] + } +} ` tinkerbellKant = ` - { - "network":{ - "interfaces":[ - { - "dhcp":{ - "mac":"ec:0d:9a:c0:01:0c", - "hostname":"server001", - "lease_time":86400, - "arch":"x86_64", - "ip":{ - "address":"192.168.1.5", - "netmask":"255.255.255.248", - "gateway":"192.168.1.1" - } - }, - "netboot":{ - "allow_pxe":true, - "allow_workflow":true, - "ipxe":{ - "url":"http://url/menu.ipxe", - "contents":"#!ipxe" - }, - "osie":{ - "kernel":"vmlinuz-x86_64" - } - } - } - ] - }, - "id":"fde7c87c-d154-447e-9fce-7eb7bdec90c0", - "metadata": "{\"components\":{\"id\":\"bc9ce39b-7f18-425b-bc7b-067914fa9786\",\"type\":\"DiskComponent\"},\"instance\":{\"facility\":\"sjc1\",\"hostname\":\"tink-provisioner\",\"id\":\"f955e31a-cab6-44d6-872c-9614c2024bb4\"},\"userdata\":\"#!/bin/bash\\n\\necho \\\"Hello world!\\\"\"}" - } +{ + "id": "fde7c87c-d154-447e-9fce-7eb7bdec90c0", + "metadata": "{\"components\":{\"id\":\"bc9ce39b-7f18-425b-bc7b-067914fa9786\",\"type\":\"DiskComponent\"},\"instance\":{\"facility\":\"sjc1\",\"hostname\":\"tink-provisioner\",\"id\":\"f955e31a-cab6-44d6-872c-9614c2024bb4\"},\"userdata\":\"#!/bin/bash\\n\\necho \\\"Hello world!\\\"\"}", + "network": { + "interfaces": [ + { + "dhcp": { + "arch": "x86_64", + "hostname": "server001", + "ip": { + "address": "192.168.1.5", + "gateway": "192.168.1.1", + "netmask": "255.255.255.248" + }, + "lease_time": 86400, + "mac": "ec:0d:9a:c0:01:0c" + }, + "netboot": { + "allow_pxe": true, + "allow_workflow": true, + "ipxe": { + "contents": "#!ipxe", + "url": "http://url/menu.ipxe" + }, + "osie": { + "kernel": "vmlinuz-x86_64" + } + } + } + ] + } +} ` tinkerbellKantEC2 = ` { - "id":"0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94", - "network":{ - "interfaces":[ - { - "dhcp":{ - "ip":{ - "address":"192.168.1.5", - "gateway":"192.168.1.1", - "netmask":"255.255.255.248" - }, - "mac":"b4:96:91:5f:af:c0", - "arch":"x86_64" - }, - "netboot":{ - "allow_pxe":true, - "allow_workflow":true - } - } - ] - }, - "metadata":"{\"components\":{\"id\":\"bc9ce39b-7f18-425b-bc7b-067914fa9786\",\"type\":\"DiskComponent\"},\"instance\":{\"api_url\":\"https://metadata.packet.net\",\"class\":\"c3.small.x86\",\"customdata\":{},\"facility\":\"sjc1\",\"hostname\":\"tink-provisioner\",\"id\":\"7c9a5711-aadd-4fa0-8e57-789431626a27\",\"iqn\":\"iqn.2020-06.net.packet:device.7c9a5711\",\"network\":{\"addresses\":[{\"address\":\"139.175.86.114\",\"address_family\":4,\"cidr\":31,\"created_at\":\"2020-06-19T04:16:08Z\",\"enabled\":true,\"gateway\":\"139.175.86.113\",\"id\":\"99e15f8e-6eab-40db-9c6f-69a69ef9854f\",\"management\":true,\"netmask\":\"255.255.255.254\",\"network\":\"139.175.86.113\",\"parent_block\":{\"cidr\":31,\"href\":\"/ips/179580b0-3ae4-4fc0-8cbe-4f34174bebb4\",\"netmask\":\"255.255.255.254\",\"network\":\"139.175.86.113\"},\"public\":true},{\"address\":\"2604:1380:1000:ca00::7\",\"address_family\":6,\"cidr\":127,\"created_at\":\"2020-06-19T04:16:08Z\",\"enabled\":true,\"gateway\":\"2604:1380:1000:ca00::6\",\"id\":\"f4b24331-c6cf-4ae4-899b-e78f223b2c57\",\"management\":true,\"netmask\":\"ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe\",\"network\":\"2604:1380:1000:ca00::6\",\"parent_block\":{\"cidr\":56,\"href\":\"/ips/960aa63d-eeb6-410e-8242-1d6e2e7733fc\",\"netmask\":\"ffff:ffff:ffff:ff00:0000:0000:0000:0000\",\"network\":\"2604:1380:1000:ca00:0000:0000:0000:0000\"},\"public\":true},{\"address\":\"10.87.63.3\",\"address_family\":4,\"cidr\":31,\"created_at\":\"2020-06-19T04:16:08Z\",\"enabled\":true,\"gateway\":\"10.87.63.2\",\"id\":\"5cca13a9-43d0-45a6-9ed7-3d9e2fbf0e87\",\"management\":true,\"netmask\":\"255.255.255.254\",\"network\":\"10.87.63.2\",\"parent_block\":{\"cidr\":25,\"href\":\"/ips/7cde0a1b-d787-4a10-9c96-4049c7d5eeb3\",\"netmask\":\"255.255.255.128\",\"network\":\"10.87.63.0\"},\"public\":false}],\"bonding\":{\"link_aggregation\":null,\"mac\":\"b4:96:91:5f:ad:d8\",\"mode\":4},\"interfaces\":[{\"bond\":\"bond0\",\"mac\":\"b4:96:91:5f:ad:d8\",\"name\":\"eth0\"},{\"bond\":\"bond0\",\"mac\":\"b4:96:91:5f:ad:d9\",\"name\":\"eth1\"}]},\"operating_system\":{\"distro\":\"ubuntu\",\"image_tag\":\"f8f0331d31935319dfa8b6d551b5680840d7944f\",\"license_activation\":{\"state\":\"unlicensed\"},\"slug\":\"ubuntu_18_04\",\"version\":\"18.04\"},\"phone_home_url\":\"http://tinkerbell.sjc1.packet.net/phone-home\",\"plan\":\"c3.small.x86\",\"private_subnets\":[\"10.0.0.0/8\"],\"specs\":{\"cpus\":[{\"count\":1,\"type\":\"EPYC 3151 4 Core Processor @ 2.7GHz\"}],\"drives\":[{\"category\":\"boot\",\"count\":2,\"size\":\"240GB\",\"type\":\"SSD\"}],\"features\":{},\"memory\":{\"total\":\"16GB\"},\"nics\":[{\"count\":2,\"type\":\"10Gbps\"}]},\"ssh_keys\":[],\"storage\":{\"disks\":[{\"device\":\"/dev/sda\",\"partitions\":[{\"label\":\"BIOS\",\"number\":1,\"size\":4096},{\"label\":\"SWAP\",\"number\":2,\"size\":\"3993600\"},{\"label\":\"ROOT\",\"number\":3,\"size\":0}],\"wipeTable\":true}],\"filesystems\":[{\"mount\":{\"create\":{\"options\":[\"-L\",\"ROOT\"]},\"device\":\"/dev/sda3\",\"format\":\"ext4\",\"point\":\"/\"}},{\"mount\":{\"create\":{\"options\":[\"-L\",\"SWAP\"]},\"device\":\"/dev/sda2\",\"format\":\"swap\",\"point\":\"none\"}}]},\"switch_short_id\":\"68c7fa13\",\"tags\":[\"hello\",\"test\"],\"user_state_url\":\"http://tinkerbell.sjc1.packet.net/events\",\"volumes\":[]},\"userdata\":\"#!/bin/bash\\n\\necho \\\"Hello world!\\\"\"}" + "id": "0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94", + "metadata": "{\"components\":{\"id\":\"bc9ce39b-7f18-425b-bc7b-067914fa9786\",\"type\":\"DiskComponent\"},\"instance\":{\"api_url\":\"https://metadata.packet.net\",\"class\":\"c3.small.x86\",\"customdata\":{},\"facility\":\"sjc1\",\"hostname\":\"tink-provisioner\",\"id\":\"7c9a5711-aadd-4fa0-8e57-789431626a27\",\"iqn\":\"iqn.2020-06.net.packet:device.7c9a5711\",\"network\":{\"addresses\":[{\"address\":\"139.175.86.114\",\"address_family\":4,\"cidr\":31,\"created_at\":\"2020-06-19T04:16:08Z\",\"enabled\":true,\"gateway\":\"139.175.86.113\",\"id\":\"99e15f8e-6eab-40db-9c6f-69a69ef9854f\",\"management\":true,\"netmask\":\"255.255.255.254\",\"network\":\"139.175.86.113\",\"parent_block\":{\"cidr\":31,\"href\":\"/ips/179580b0-3ae4-4fc0-8cbe-4f34174bebb4\",\"netmask\":\"255.255.255.254\",\"network\":\"139.175.86.113\"},\"public\":true},{\"address\":\"2604:1380:1000:ca00::7\",\"address_family\":6,\"cidr\":127,\"created_at\":\"2020-06-19T04:16:08Z\",\"enabled\":true,\"gateway\":\"2604:1380:1000:ca00::6\",\"id\":\"f4b24331-c6cf-4ae4-899b-e78f223b2c57\",\"management\":true,\"netmask\":\"ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe\",\"network\":\"2604:1380:1000:ca00::6\",\"parent_block\":{\"cidr\":56,\"href\":\"/ips/960aa63d-eeb6-410e-8242-1d6e2e7733fc\",\"netmask\":\"ffff:ffff:ffff:ff00:0000:0000:0000:0000\",\"network\":\"2604:1380:1000:ca00:0000:0000:0000:0000\"},\"public\":true},{\"address\":\"10.87.63.3\",\"address_family\":4,\"cidr\":31,\"created_at\":\"2020-06-19T04:16:08Z\",\"enabled\":true,\"gateway\":\"10.87.63.2\",\"id\":\"5cca13a9-43d0-45a6-9ed7-3d9e2fbf0e87\",\"management\":true,\"netmask\":\"255.255.255.254\",\"network\":\"10.87.63.2\",\"parent_block\":{\"cidr\":25,\"href\":\"/ips/7cde0a1b-d787-4a10-9c96-4049c7d5eeb3\",\"netmask\":\"255.255.255.128\",\"network\":\"10.87.63.0\"},\"public\":false}],\"bonding\":{\"link_aggregation\":null,\"mac\":\"b4:96:91:5f:ad:d8\",\"mode\":4},\"interfaces\":[{\"bond\":\"bond0\",\"mac\":\"b4:96:91:5f:ad:d8\",\"name\":\"eth0\"},{\"bond\":\"bond0\",\"mac\":\"b4:96:91:5f:ad:d9\",\"name\":\"eth1\"}]},\"operating_system\":{\"distro\":\"ubuntu\",\"image_tag\":\"f8f0331d31935319dfa8b6d551b5680840d7944f\",\"license_activation\":{\"state\":\"unlicensed\"},\"slug\":\"ubuntu_18_04\",\"version\":\"18.04\"},\"phone_home_url\":\"http://tinkerbell.sjc1.packet.net/phone-home\",\"plan\":\"c3.small.x86\",\"private_subnets\":[\"10.0.0.0/8\"],\"specs\":{\"cpus\":[{\"count\":1,\"type\":\"EPYC 3151 4 Core Processor @ 2.7GHz\"}],\"drives\":[{\"category\":\"boot\",\"count\":2,\"size\":\"240GB\",\"type\":\"SSD\"}],\"features\":{},\"memory\":{\"total\":\"16GB\"},\"nics\":[{\"count\":2,\"type\":\"10Gbps\"}]},\"ssh_keys\":[],\"storage\":{\"disks\":[{\"device\":\"/dev/sda\",\"partitions\":[{\"label\":\"BIOS\",\"number\":1,\"size\":4096},{\"label\":\"SWAP\",\"number\":2,\"size\":\"3993600\"},{\"label\":\"ROOT\",\"number\":3,\"size\":0}],\"wipeTable\":true}],\"filesystems\":[{\"mount\":{\"create\":{\"options\":[\"-L\",\"ROOT\"]},\"device\":\"/dev/sda3\",\"format\":\"ext4\",\"point\":\"/\"}},{\"mount\":{\"create\":{\"options\":[\"-L\",\"SWAP\"]},\"device\":\"/dev/sda2\",\"format\":\"swap\",\"point\":\"none\"}}]},\"switch_short_id\":\"68c7fa13\",\"tags\":[\"hello\",\"test\"],\"user_state_url\":\"http://tinkerbell.sjc1.packet.net/events\",\"volumes\":[]},\"userdata\":\"#!/bin/bash\\n\\necho \\\"Hello world!\\\"\"}", + "network": { + "interfaces": [ + { + "dhcp": { + "arch": "x86_64", + "ip": { + "address": "192.168.1.5", + "gateway": "192.168.1.1", + "netmask": "255.255.255.248" + }, + "mac": "b4:96:91:5f:af:c0" + }, + "netboot": { + "allow_pxe": true, + "allow_workflow": true + } + } + ] + } } ` tinkerbellKantEC2SpotEmpty = ` { - "id":"0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94", - "network":{ - "interfaces":[ - { - "dhcp":{ - "ip":{ - "address":"192.168.1.5", - "gateway":"192.168.1.1", - "netmask":"255.255.255.248" - }, - "mac":"b4:96:91:5f:af:c0", - "arch":"x86_64" - }, - "netboot":{ - "allow_pxe":true, - "allow_workflow":true - } - } - ] - }, - "metadata":"{\"instance\":{\"spot\":{}}}" + "id": "0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94", + "metadata": "{\"instance\":{\"spot\":{}}}", + "network": { + "interfaces": [ + { + "dhcp": { + "arch": "x86_64", + "ip": { + "address": "192.168.1.5", + "gateway": "192.168.1.1", + "netmask": "255.255.255.248" + }, + "mac": "b4:96:91:5f:af:c0" + }, + "netboot": { + "allow_pxe": true, + "allow_workflow": true + } + } + ] + } } ` tinkerbellKantEC2SpotWithTermination = ` { - "id":"0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94", - "network":{ - "interfaces":[ - { - "dhcp":{ - "ip":{ - "address":"192.168.1.5", - "gateway":"192.168.1.1", - "netmask":"255.255.255.248" - }, - "mac":"b4:96:91:5f:af:c0", - "arch":"x86_64" - }, - "netboot":{ - "allow_pxe":true, - "allow_workflow":true - } - } - ] - }, - "metadata":"{\"instance\":{\"spot\":{\"termination_time\":\"now\"}}}" + "id": "0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94", + "metadata": "{\"instance\":{\"spot\":{\"termination_time\":\"now\"}}}", + "network": { + "interfaces": [ + { + "dhcp": { + "arch": "x86_64", + "ip": { + "address": "192.168.1.5", + "gateway": "192.168.1.1", + "netmask": "255.255.255.248" + }, + "mac": "b4:96:91:5f:af:c0" + }, + "netboot": { + "allow_pxe": true, + "allow_workflow": true + } + } + ] + } } ` // tinkerbellFilterMetadata is used for testing the filterMetadata function and has the 'metadata' field represented as an object (as opposed to string)