diff --git a/api/api.go b/api/api.go index d7ccc95..5709004 100644 --- a/api/api.go +++ b/api/api.go @@ -12,6 +12,13 @@ type MetalConfig struct { HMAC string `json:"hmac,omitempty"` NTPServers []string `json:"ntp_servers,omitempty"` Partition string `json:"partition"` + + // metal-apiserver related fields + MetalAPIServerUrl string `json:"metal_apiserver_url"` + MetalAPIServerTokenFile string `json:"-"` + MetalHammerTenant string `json:"-"` + MetalHammerToken string `json:"metal_hammer_token"` + // Logging contains logging configurations passed to metal-hammer Logging *Logging `json:"logging,omitempty"` } diff --git a/go.mod b/go.mod index 5d6e029..dad6b46 100644 --- a/go.mod +++ b/go.mod @@ -1,30 +1,35 @@ module github.com/metal-stack/pixie -go 1.25 +go 1.27 require ( - github.com/metal-stack/metal-api v0.42.4 + github.com/metal-stack/api v0.5.6-0.20260922094948-2ae319bc7599 github.com/metal-stack/v v1.0.3 github.com/pin/tftp/v3 v3.1.0 github.com/prometheus/client_golang v1.23.2 github.com/spf13/cobra v1.10.1 github.com/spf13/viper v1.21.0 - github.com/stretchr/testify v1.11.1 - golang.org/x/crypto v0.43.0 - golang.org/x/net v0.46.0 - google.golang.org/grpc v1.76.0 + github.com/stretchr/testify v1.12.1 + golang.org/x/crypto v0.55.0 + golang.org/x/net v0.58.0 ) require ( + buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.12-20260825204119-511051f7f437.1 // indirect + connectrpc.com/connect v1.20.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/go-viper/mapstructure/v2 v2.4.0 // indirect + github.com/golang-jwt/jwt/v5 v5.3.1 // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/klauspost/compress v1.20.0 // indirect + github.com/klauspost/connect-compress/v2 v2.1.1 // indirect + github.com/minio/minlz v1.2.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_model v0.6.2 // indirect github.com/prometheus/common v0.67.2 // indirect github.com/prometheus/procfs v0.19.1 // indirect @@ -34,10 +39,8 @@ require ( github.com/spf13/pflag v1.0.10 // indirect github.com/subosito/gotenv v1.6.0 // indirect go.yaml.in/yaml/v2 v2.4.3 // indirect - go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/sys v0.37.0 // indirect - golang.org/x/text v0.30.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 // indirect - google.golang.org/protobuf v1.36.10 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect + go.yaml.in/yaml/v3 v3.0.5 // indirect + golang.org/x/sys v0.47.0 // indirect + golang.org/x/text v0.41.0 // indirect + google.golang.org/protobuf v1.36.12 // indirect ) diff --git a/go.sum b/go.sum index d09cf22..4bed43e 100644 --- a/go.sum +++ b/go.sum @@ -1,48 +1,48 @@ +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.12-20260825204119-511051f7f437.1 h1:Slv0uGxx219srASyiaI5C9cDlyG8kNDcXpTSYcuAeE4= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.12-20260825204119-511051f7f437.1/go.mod h1:TCt1lluMFnctISJXvkIQ4x3ABrPuUKCWKyjKdkJNBpw= +connectrpc.com/connect v1.20.0 h1:6TNDAB+WeNd2uolWNlYczB5E0KNNaVMNUEx8JEUsPmQ= +connectrpc.com/connect v1.20.0/go.mod h1:A2ygJrukXwWy32vkCAAHNVguZrqZ+jeZ9rGRnGR4dN4= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= -github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= -github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY= +github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= -github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/klauspost/compress v1.20.0 h1:a3C1ke2ohxFymNlb2HWAHjDeKCI90scRskErZkR0ezA= +github.com/klauspost/compress v1.20.0/go.mod h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI= +github.com/klauspost/connect-compress/v2 v2.1.1 h1:ycZNp4rWOZBodVE2Ls5AzK4aHkyK+GteEfzRZgKNs+c= +github.com/klauspost/connect-compress/v2 v2.1.1/go.mod h1:9oilsPHJMzGKkjafSBk9J7iVo4mO+dw0G0KSdVpnlVE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/metal-stack/metal-api v0.42.4 h1:4DVa8INyW2AFV5ryQSD9rtwLiyPa3bAGttJlFXtldMg= -github.com/metal-stack/metal-api v0.42.4/go.mod h1:fzetGND6XWSZyVM/BeryIL5JDC+M6ADIWtBvBJbXKNo= +github.com/metal-stack/api v0.5.6-0.20260922094948-2ae319bc7599 h1:sNUoggBJpLPNw39I3vB9Cn+vJEpzMbbsR24xKWOcxtI= +github.com/metal-stack/api v0.5.6-0.20260922094948-2ae319bc7599/go.mod h1:rWdj0dTAg2w/WuQhIZ+JVp9b68v6VVCm1k7sLx4U+PQ= github.com/metal-stack/v v1.0.3 h1:Sh2oBlnxrCUD+mVpzfC8HiqL045YWkxs0gpTvkjppqs= github.com/metal-stack/v v1.0.3/go.mod h1:YTahEu7/ishwpYKnp/VaW/7nf8+PInogkfGwLcGPdXg= +github.com/minio/minlz v1.2.0 h1:6IOBuiHg04QxvbFfgFLT/9sMaO/UhL7S+ApW1mK8q5A= +github.com/minio/minlz v1.2.0/go.mod h1:Ls9H7nlkASeCcdl5thjVD5Eraj6z+zGa7xtq57jIKD4= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pin/tftp/v3 v3.1.0 h1:rQaxd4pGwcAJnpId8zC+O2NX3B2/NscjDZQaqEjuE7c= github.com/pin/tftp/v3 v3.1.0/go.mod h1:xwQaN4viYL019tM4i8iecm++5cGxSqen6AJEOEyEI0w= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= @@ -67,50 +67,31 @@ github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE= +github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUmoNlxoYthg= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= -go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= -go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= -go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= -go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= -go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= -go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= -go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= -go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= -go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= -go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= -go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= -go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= -go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= +go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= -golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= +golang.org/x/crypto v0.55.0 h1:+KWHjbgOaAQ66dh/YlkZKHlz9ZUlq61AFirAR9ntP8M= +golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= -golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= +golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To= +golang.org/x/net v0.58.0/go.mod h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= -golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= +golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= -golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= -gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= -gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 h1:M1rk8KBnUsBDg1oPGHNCxG4vc1f49epmTO7xscSajMk= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= -google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= -google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= -google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= -google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8= +golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M= +google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc= +google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pixiecore/booters.go b/pixiecore/booters.go index 9064b63..53634e6 100644 --- a/pixiecore/booters.go +++ b/pixiecore/booters.go @@ -29,7 +29,8 @@ import ( "text/template" "time" - v1 "github.com/metal-stack/metal-api/pkg/api/v1" + "github.com/metal-stack/api/go/client" + infrav2 "github.com/metal-stack/api/go/metalstack/infra/v2" "github.com/metal-stack/pixie/api" ) @@ -50,9 +51,9 @@ func APIBooter(url string, timeout time.Duration) (Booter, error) { return ret, nil } -func GRPCBooter(log *slog.Logger, client *GrpcClient, partition string, metalAPIConfig *api.MetalConfig) (Booter, error) { +func GRPCBooter(log *slog.Logger, v2client client.Client, partition string, metalAPIConfig *api.MetalConfig) (Booter, error) { ret := &grpcbooter{ - grpc: client, + v2client: v2client, partition: partition, log: log, config: metalAPIConfig, @@ -72,7 +73,8 @@ type apibooter struct { type grpcbooter struct { apibooter - grpc *GrpcClient + // v1client *GrpcClient + v2client client.Client config *api.MetalConfig partition string log *slog.Logger @@ -87,11 +89,11 @@ func (g *grpcbooter) BootSpec(m Machine) (*Spec, error) { var r rawSpec if m.GUID != "" { // Very first dhcp call which contains Machine UUID, tell metal-api this uuid - req := &v1.BootServiceDhcpRequest{ - Uuid: string(m.GUID), - } - g.log.Info("dhcp", "req", req) - _, err := g.grpc.BootService().Dhcp(ctx, req) + g.log.Info("dhcp", "machine-guid", m.GUID) + _, err := g.v2client.Infrav2().Boot().Dhcp(ctx, &infrav2.BootServiceDhcpRequest{ + Uuid: m.GUID, + Partition: g.partition, + }) if err != nil { g.log.Error("boot", "error", err) return nil, err @@ -99,19 +101,25 @@ func (g *grpcbooter) BootSpec(m Machine) (*Spec, error) { r = rawSpec{} } else { // machine asks for a dhcp answer, ask metal-api for a proper response in this partition - req := &v1.BootServiceBootRequest{ - Mac: m.MAC.String(), - PartitionId: g.partition, - } - g.log.Info("boot", "req", req) - resp, err := g.grpc.BootService().Boot(ctx, req) + g.log.Info("boot", "machine-mac", m.MAC.String()) + resp, err := g.v2client.Infrav2().Boot().Boot(ctx, &infrav2.BootServiceBootRequest{ + Mac: m.MAC.String(), + Partition: g.partition, + }) if err != nil { g.log.Error("boot", "error", err) return nil, err } g.log.Info("boot", "resp", resp) - cmdline := []string{resp.GetCmdline(), fmt.Sprintf("PIXIE_API_URL=%s", g.config.PixieAPIURL)} + var cmdline []string + + if resp.Cmdline != nil { + cmdline = append(cmdline, *resp.Cmdline) + } + + cmdline = append(cmdline, fmt.Sprintf("PIXIE_API_URL=%s", g.config.PixieAPIURL)) + if g.config.Debug { cmdline = append(cmdline, "DEBUG=1") } diff --git a/pixiecore/cli/grpccmd.go b/pixiecore/cli/grpccmd.go index 8d36001..b5ea72a 100644 --- a/pixiecore/cli/grpccmd.go +++ b/pixiecore/cli/grpccmd.go @@ -16,12 +16,17 @@ package cli import ( "fmt" + "log/slog" "net/url" "os" "strings" + "time" + "github.com/metal-stack/api/go/client" + apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" "github.com/metal-stack/pixie/api" "github.com/metal-stack/pixie/pixiecore" + "github.com/metal-stack/v" "github.com/spf13/cobra" ) @@ -42,20 +47,54 @@ the Pixiecore boot API. The specification can be found at .`, if err != nil { fatalf("unable to create metal-api config: %s", err) } - client, err := pixiecore.NewGrpcClient(s.Log, metalAPIConfig) + + tokenPersister, err := client.NewFilesystemTokenPersister(metalAPIConfig.MetalAPIServerTokenFile) + if err != nil { + fatalf("error creating token persister: %s", err) + } + + token, err := os.ReadFile(metalAPIConfig.MetalAPIServerTokenFile) + if err != nil { + fatalf("error reading token: %s", err) + } + + v2client, err := client.New(&client.DialConfig{ + BaseURL: metalAPIConfig.MetalAPIServerUrl, + Token: strings.TrimSpace(string(token)), + UserAgent: "pixie", + Log: slog.Default(), + TokenRenewal: &client.TokenRenewal{ + PersistTokenFn: tokenPersister, + }, + }) if err != nil { - fatalf("unable to create grpc client: %s", err) + fatalf("failed to create metal-apiserver client: %s", err) } + partition, err := cmd.Flags().GetString("partition") if err != nil { - fatalf("Error reading flag: %s", err) + fatalf("error reading flag: %s", err) } - booter, err := pixiecore.GRPCBooter(s.Log, client, partition, metalAPIConfig) + + booter, err := pixiecore.GRPCBooter(s.Log, v2client, partition, metalAPIConfig) if err != nil { fatalf("unable to create grpc booter: %s", err) } + s.Booter = booter s.MetalConfig = metalAPIConfig + s.V2Client = v2client + + v2client.Ping(cmd.Context(), &client.PingConfig{ + ComponentType: apiv2.ComponentType_COMPONENT_TYPE_METAL_BMC, + StartedAt: time.Now(), + Version: apiv2.Version{ + Version: v.Version, + Revision: v.Revision, + GitSha1: v.GitSHA1, + BuildDate: v.BuildDate, + }, + }) fmt.Println(s.Serve()) }} @@ -77,6 +116,10 @@ func init() { grpcCmd.Flags().StringSlice("ntp-servers", nil, "custom ntp-servers") grpcCmd.Flags().Bool("metal-hammer-debug", true, "set metal-hammer to debug") + grpcCmd.Flags().String("metal-apiserver-url", "", "url to access the metal-apiserver") + grpcCmd.Flags().String("metal-apiserver-token-file", "", "token file path to access the metal-apiserver") + grpcCmd.Flags().String("metal-hammer-tenant", "", "the metal-hammer tenant in the metal-apiserver for which tokens will be issued") + // metal-hammer remote logging configuration grpcCmd.Flags().String("metal-hammer-logging-endpoint", "", "set metal-hammer to send logs to this endpoint") grpcCmd.Flags().String("metal-hammer-logging-user", "", "set metal-hammer to send logs to a remote endpoint and authenticate with this user") @@ -139,6 +182,24 @@ func getMetalAPIConfig(cmd *cobra.Command) (*api.MetalConfig, error) { if err != nil { return nil, fmt.Errorf("unable to parse pixie-api-url: %w", err) } + + metalApiServerUrl, err := cmd.Flags().GetString("metal-apiserver-url") + if err != nil { + return nil, fmt.Errorf("error reading flag: %w", err) + } + _, err = url.Parse(metalApiServerUrl) + if err != nil { + return nil, fmt.Errorf("unable to parse metal-apiserver-url: %w", err) + } + metalApiServerTokenFile, err := cmd.Flags().GetString("metal-apiserver-token-file") + if err != nil { + return nil, fmt.Errorf("error reading flag: %w", err) + } + metalHammerTenant, err := cmd.Flags().GetString("metal-hammer-tenant") + if err != nil { + return nil, fmt.Errorf("error reading flag: %w", err) + } + ntpServers, err := cmd.Flags().GetStringSlice("ntp-servers") if err != nil { return nil, fmt.Errorf("unable reading ntp-servers flag: %w", err) @@ -220,16 +281,19 @@ func getMetalAPIConfig(cmd *cobra.Command) (*api.MetalConfig, error) { } return &api.MetalConfig{ - Debug: metalHammerDebug, - GRPCAddress: grpcAddress, - MetalAPIUrl: metalAPIUrl, - PixieAPIURL: pixieAPIUrl, - CACert: string(caCert), - Cert: string(clientCert), - Key: string(clientKey), - HMAC: hmac, - NTPServers: ntpServers, - Logging: logging, - Partition: partition, + Debug: metalHammerDebug, + GRPCAddress: grpcAddress, + MetalAPIUrl: metalAPIUrl, + PixieAPIURL: pixieAPIUrl, + CACert: string(caCert), + Cert: string(clientCert), + Key: string(clientKey), + HMAC: hmac, + NTPServers: ntpServers, + Logging: logging, + Partition: partition, + MetalAPIServerUrl: metalApiServerUrl, + MetalAPIServerTokenFile: metalApiServerTokenFile, + MetalHammerTenant: metalHammerTenant, }, nil } diff --git a/pixiecore/grpc.go b/pixiecore/grpc.go deleted file mode 100644 index 23d7ad7..0000000 --- a/pixiecore/grpc.go +++ /dev/null @@ -1,66 +0,0 @@ -package pixiecore - -import ( - "crypto/tls" - "crypto/x509" - "errors" - "log/slog" - "time" - - v1 "github.com/metal-stack/metal-api/pkg/api/v1" - "github.com/metal-stack/pixie/api" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials" - "google.golang.org/grpc/keepalive" -) - -type GrpcClient struct { - log *slog.Logger - conn grpc.ClientConnInterface -} - -// NewGrpcClient fetches the address and certificates from metal-core needed to communicate with metal-api via grpc, -// and returns a new grpc client that can be used to invoke all provided grpc endpoints. -func NewGrpcClient(log *slog.Logger, config *api.MetalConfig) (*GrpcClient, error) { - clientCert, err := tls.X509KeyPair([]byte(config.Cert), []byte(config.Key)) - if err != nil { - return nil, err - } - - caCertPool := x509.NewCertPool() - ok := caCertPool.AppendCertsFromPEM([]byte(config.CACert)) - if !ok { - return nil, errors.New("bad certificate") - } - - kacp := keepalive.ClientParameters{ - Time: 10 * time.Second, // send pings every 10 seconds if there is no activity - Timeout: time.Second, // wait 1 second for ping ack before considering the connection dead - PermitWithoutStream: true, // send pings even without active streams - } - - tlsConfig := &tls.Config{ - RootCAs: caCertPool, - Certificates: []tls.Certificate{clientCert}, - MinVersion: tls.VersionTLS12, - } - - grpcOpts := []grpc.DialOption{ - grpc.WithKeepaliveParams(kacp), - grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)), - } - - conn, err := grpc.NewClient(config.GRPCAddress, grpcOpts...) - if err != nil { - return nil, err - } - - return &GrpcClient{ - log: log, - conn: conn, - }, nil -} - -func (c *GrpcClient) BootService() v1.BootServiceClient { - return v1.NewBootServiceClient(c.conn) -} diff --git a/pixiecore/http.go b/pixiecore/http.go index 4482a28..2372a54 100644 --- a/pixiecore/http.go +++ b/pixiecore/http.go @@ -26,6 +26,9 @@ import ( "strconv" "text/template" "time" + + infrav2 "github.com/metal-stack/api/go/metalstack/infra/v2" + "google.golang.org/protobuf/types/known/durationpb" ) func serveHTTP(l net.Listener, handlers ...func(*http.ServeMux)) error { @@ -44,6 +47,7 @@ func (s *Server) serveHTTP(mux *http.ServeMux) { mux.HandleFunc("/_/file", s.handleFile) mux.HandleFunc("/_/booting", s.handleBooting) mux.HandleFunc("/certs", s.handleCerts) + mux.HandleFunc("/config/{id}", s.handleConfig) } func (s *Server) handleIpxe(w http.ResponseWriter, r *http.Request) { @@ -242,3 +246,42 @@ func (s *Server) handleCerts(w http.ResponseWriter, r *http.Request) { return } } + +func (s *Server) handleConfig(w http.ResponseWriter, r *http.Request) { + // request must be in the form of /config/7ba734c9-6145-4b7a-817c-8b5c72fb7057 + // with the machineUUID as path parameter + // 3 days max lifetime because hammer reboots every 2 days max. + + machineUUID := r.PathValue("id") + s.Log.Debug("handleConfig", "machine-uuid", machineUUID) + + resp, err := s.V2Client.Infrav2().Boot().MachineToken(r.Context(), &infrav2.BootServiceMachineTokenRequest{ + User: s.MetalConfig.MetalHammerTenant, + Uuid: machineUUID, + Expires: durationpb.New(3 * 24 * time.Hour), + }) + if err != nil { + s.Log.Error("unable to create a token for the metal-hammer", "error", err) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + metalConfig := s.MetalConfig + // store to created secret to be shipped to metal-hammer + metalConfig.MetalHammerToken = resp.Secret + + js, err := json.MarshalIndent(metalConfig, "", " ") + if err != nil { + s.Log.Error("handleConfig unable to marshal grpc config", "error", err) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + s.Log.Debug("handleConfig return grpc config") + w.Header().Set("Content-Type", "application/json") + _, err = w.Write(js) + if err != nil { + s.Log.Error("handleConfig unable to write grpc config to response", "error", err) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } +} diff --git a/pixiecore/pixiecore.go b/pixiecore/pixiecore.go index 460d903..133d238 100644 --- a/pixiecore/pixiecore.go +++ b/pixiecore/pixiecore.go @@ -26,6 +26,7 @@ import ( "sync" "text/template" + "github.com/metal-stack/api/go/client" "github.com/metal-stack/pixie/api" "github.com/metal-stack/pixie/dhcp4" "github.com/metal-stack/v" @@ -206,6 +207,9 @@ type Server struct { events map[string][]machineEvent MetalConfig *api.MetalConfig + + // V2Client to talk to the metal-apiserver + V2Client client.Client } // Serve listens for machines attempting to boot, and uses Booter to