diff --git a/.gitignore b/.gitignore index ed0e41ac..3cf55129 100644 --- a/.gitignore +++ b/.gitignore @@ -52,3 +52,5 @@ pkg # NPM artifacts internal/hardhat/node_modules/ + +.DS_Store \ No newline at end of file diff --git a/cli/tui/config/enable-param.go b/cli/tui/config/enable-param.go index 5055d03c..7f43bd1e 100644 --- a/cli/tui/config/enable-param.go +++ b/cli/tui/config/enable-param.go @@ -8,14 +8,14 @@ import ( ) type enableParamInstance struct { - info *config.ModuleInfo - intance *config.ModuleInstance + info *config.ModuleInfo + instance *config.ModuleInstance } func NewEnableParamInstance(info *config.ModuleInfo, instance *config.ModuleInstance) *enableParamInstance { return &enableParamInstance{ - info: info, - intance: instance, + info: info, + instance: instance, } } @@ -85,7 +85,7 @@ func (e *enableParamInstance) GetMetadata() config.IParameter { } func (e *enableParamInstance) GetValue() any { - return e.intance.Enabled + return e.instance.Enabled } func (e *enableParamInstance) SetValue(value any) error { @@ -93,12 +93,12 @@ func (e *enableParamInstance) SetValue(value any) error { if !ok { return fmt.Errorf("invalid value type for module \"%s\" enable flag: %T", e.info.Descriptor.GetFullyQualifiedModuleName(), value) } - e.intance.Enabled = val + e.instance.Enabled = val return nil } func (e *enableParamInstance) String() string { - return strconv.FormatBool(e.intance.Enabled) + return strconv.FormatBool(e.instance.Enabled) } func (e *enableParamInstance) Validate() []error { diff --git a/go.mod b/go.mod index 7f05357c..9af72ddf 100644 --- a/go.mod +++ b/go.mod @@ -21,12 +21,14 @@ require ( github.com/rivo/tview v0.0.0-20230208211350-7dfff1ce7854 // DO NOT UPGRADE github.com/stretchr/testify v1.10.0 github.com/urfave/cli/v2 v2.27.5 - golang.org/x/term v0.28.0 + golang.org/x/term v0.29.0 gopkg.in/natefinch/lumberjack.v2 v2.2.1 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 ) +require github.com/gorilla/mux v1.8.1 + require ( github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect @@ -51,8 +53,7 @@ require ( github.com/go-viper/mapstructure/v2 v2.0.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/gorilla/mux v1.8.1 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect @@ -83,26 +84,27 @@ require ( github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect - go.opentelemetry.io/otel v1.34.0 // indirect + go.opentelemetry.io/otel v1.35.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 // indirect - go.opentelemetry.io/otel/metric v1.34.0 // indirect - go.opentelemetry.io/otel/sdk v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 // indirect + go.opentelemetry.io/otel/metric v1.35.0 // indirect + go.opentelemetry.io/otel/sdk v1.35.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.34.0 // indirect - go.opentelemetry.io/otel/trace v1.34.0 // indirect + go.opentelemetry.io/otel/trace v1.35.0 // indirect go.opentelemetry.io/proto/otlp v1.5.0 // indirect - golang.org/x/crypto v0.32.0 // indirect + golang.org/x/crypto v0.33.0 // indirect golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect - golang.org/x/net v0.34.0 // indirect - golang.org/x/sync v0.10.0 // indirect - golang.org/x/sys v0.29.0 // indirect - golang.org/x/text v0.21.0 // indirect + golang.org/x/net v0.35.0 // indirect + golang.org/x/sync v0.11.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/text v0.22.0 // indirect golang.org/x/time v0.5.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a // indirect + google.golang.org/grpc v1.71.0 // indirect + google.golang.org/protobuf v1.36.5 // indirect ) replace github.com/rocket-pool/smartnode/v2 => github.com/nodeset-org/rocketpool-smartnode/v2 v2.0.0-olddev.0.20250130225832-4768ad9c2c82 diff --git a/go.sum b/go.sum index f7d7e2bc..acc6605c 100644 --- a/go.sum +++ b/go.sum @@ -100,8 +100,8 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/certificate-transparency-go v1.0.10-0.20180222191210-5ab67e519c93 h1:jc2UWq7CbdszqeH6qu1ougXMIUBfSy8Pbh/anURYbGI= github.com/google/certificate-transparency-go v1.0.10-0.20180222191210-5ab67e519c93/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +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/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -109,8 +109,8 @@ github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 h1:e9Rjr40Z98/clHv5Yg79Is0NtosR5LXRvdr7o/6NwbA= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1/go.mod h1:tIxuGz/9mpox++sgp9fJjHO0+q1X9/UOWd798aAm22M= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= @@ -156,9 +156,8 @@ github.com/miekg/pkcs11 v1.0.2 h1:CIBkOawOtzJNE0B+EpRiUBzuVW7JEQAwdwhSS6YhIeg= github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366 h1:1ypTpKUfEOyX1YsJru6lLq7hrmK+QGECpJQ1PHUHuGo= github.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= @@ -205,8 +204,6 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rocket-pool/node-manager-core v0.5.2-0.20241029172412-6cb22253be3f h1:yGcY5EBYh/8f5zqyoorI3XHS/oD9uyGdbIpSOHSKWI8= -github.com/rocket-pool/node-manager-core v0.5.2-0.20241029172412-6cb22253be3f/go.mod h1:/FFOK81WO/FZO+Y/9LeBRkVE17VkyyerAb9oBh9fpag= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -256,24 +253,24 @@ go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJyS go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= -go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= -go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= +go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= +go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0 h1:ajl4QczuJVA2TU9W9AGw++86Xga/RKt//16z/yxPgdk= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0/go.mod h1:Vn3/rlOJ3ntf/Q3zAI0V5lDnTbHGaUsNUeF6nZmm7pA= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 h1:Xw8U6u2f8DK2XAkGRFV7BBLENgnTGX9i4rQRxJf+/vs= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0/go.mod h1:6KW1Fm6R/s6Z3PGXwSJN2K4eT6wQB3vXX6CVnYX9NmM= -go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= -go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= -go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= -go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk= +go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= +go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= +go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= +go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= -go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= -go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= +go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= +go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -285,8 +282,8 @@ golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= -golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM= golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -301,16 +298,16 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= -golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -328,22 +325,22 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= -golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= -golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= +golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU= +golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -356,15 +353,15 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1:gap6+3Gk41EItBuyi4XX/bp4oqJ3UwuIMl25yGinuAA= -google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= +google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a h1:nwKuGPlUAt+aR+pcrkfFRrTU1BVrSmYyYMxYbUIVHr0= +google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a/go.mod h1:3kWAYMk1I75K4vykHtKt2ycnOgpA6974V7bREqbsenU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a h1:51aaUVRocpvUOSQKM6Q7VuoaktNIaMCLuhZB6DKksq4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a/go.mod h1:uRxBH1mhmO8PGhU89cMcHaXKZqO+OfakD8QQO0oYwlQ= google.golang.org/grpc v1.0.5/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= +google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= +google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= +google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/cenkalti/backoff.v2 v2.2.1 h1:eJ9UAg01/HIHG987TwxvnzK2MgxXq97YY6rYDpY9aII= gopkg.in/cenkalti/backoff.v2 v2.2.1/go.mod h1:S0QdOvT2AlerfSBkp0O+dk+bbIMaNbEmVk876gPCthU= @@ -387,5 +384,5 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= -gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= +gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= +gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g= diff --git a/shared/adapter/client.go b/shared/adapter/client.go index 45ec1a5b..d88a1520 100644 --- a/shared/adapter/client.go +++ b/shared/adapter/client.go @@ -115,7 +115,7 @@ func getContainerID(dockerClient *client.Client, containerName string) (string, } // Run a docker exec command in the adapter container and get the result -func runCommand[RequestType any, ResponseType any]( +func RunCommand[RequestType any, ResponseType any]( c *AdapterClient, ctx context.Context, command string, diff --git a/shared/adapter/get-config-metadata.go b/shared/adapter/get-config-metadata.go index d2d241e7..70e863c9 100644 --- a/shared/adapter/get-config-metadata.go +++ b/shared/adapter/get-config-metadata.go @@ -16,7 +16,7 @@ func (c *AdapterClient) GetConfigMetadata(ctx context.Context) (config.IModuleCo configMap := map[string]any{} // Get the config from the adapter - err := runCommand[struct{}](c, ctx, GetConfigMetadataCommandString, nil, &configMap) + err := RunCommand[struct{}](c, ctx, GetConfigMetadataCommandString, nil, &configMap) if err != nil { return nil, fmt.Errorf("error getting configuration metadata: %w", err) } diff --git a/shared/adapter/process-settings.go b/shared/adapter/process-settings.go index ea84ea9d..26279d35 100644 --- a/shared/adapter/process-settings.go +++ b/shared/adapter/process-settings.go @@ -39,7 +39,7 @@ func (c *AdapterClient) ProcessSettings(ctx context.Context, oldSettings *config NewSettings: newSettings, } response := ProcessSettingsResponse{} - err := runCommand(c, ctx, ProcessSettingsCommandString, request, &response) + err := RunCommand(c, ctx, ProcessSettingsCommandString, request, &response) if err != nil { return response, fmt.Errorf("error processing module settings: %w", err) } diff --git a/shared/adapter/set-settings.go b/shared/adapter/set-settings.go index cb7b49df..e001f74a 100644 --- a/shared/adapter/set-settings.go +++ b/shared/adapter/set-settings.go @@ -27,7 +27,7 @@ func (c *AdapterClient) SetSettings(ctx context.Context, settings *config.Hyperd }, Settings: settings, } - err := runCommand[SetSettingsRequest, struct{}](c, ctx, SetSettingsCommandString, request, nil) + err := RunCommand[SetSettingsRequest, struct{}](c, ctx, SetSettingsCommandString, request, nil) if err != nil { return fmt.Errorf("error setting module settings: %w", err) } diff --git a/shared/adapter/start.go b/shared/adapter/start.go index a1635cc1..4e2b885d 100644 --- a/shared/adapter/start.go +++ b/shared/adapter/start.go @@ -25,7 +25,7 @@ func (c *AdapterClient) Start(ctx context.Context, settings *config.HyperdriveSe }, Settings: settings, } - err := runCommand[StartRequest, struct{}](c, ctx, StartCommandString, request, nil) + err := RunCommand[StartRequest, struct{}](c, ctx, StartCommandString, request, nil) if err != nil { return err } diff --git a/shared/adapter/test/command_test.go b/shared/adapter/test/command_test.go index 7e4d0359..ff50e18f 100644 --- a/shared/adapter/test/command_test.go +++ b/shared/adapter/test/command_test.go @@ -40,7 +40,7 @@ func TestGetConfigMetadata(t *testing.T) { for _, param := range cfg.GetParameters() { paramMap[param.GetID().String()] = param } - require.Len(t, paramMap, 6) + require.Len(t, paramMap, 7) exampleFloatName := "exampleFloat" require.Contains(t, paramMap, exampleFloatName) exampleFloat := paramMap[exampleFloatName] diff --git a/shared/adapter/upgrade-instance.go b/shared/adapter/upgrade-instance.go index e6e31826..68169333 100644 --- a/shared/adapter/upgrade-instance.go +++ b/shared/adapter/upgrade-instance.go @@ -23,7 +23,7 @@ func (c *AdapterClient) UpgradeInstance(ctx context.Context, instance *config.Mo Instance: instance, } response := config.ModuleInstance{} - err := runCommand(c, ctx, UpgradeInstanceCommandString, request, &response) + err := RunCommand(c, ctx, UpgradeInstanceCommandString, request, &response) if err != nil { return &response, fmt.Errorf("error upgrading settings: %w", err) } diff --git a/shared/adapter/version.go b/shared/adapter/version.go index 62ff1152..3f102714 100644 --- a/shared/adapter/version.go +++ b/shared/adapter/version.go @@ -17,7 +17,7 @@ type VersionResponse struct { // Get the version of the adapter func (c *AdapterClient) GetVersion(ctx context.Context) (string, error) { var version VersionResponse - err := runCommand[struct{}](c, ctx, VersionCommandString, nil, &version) + err := RunCommand[struct{}](c, ctx, VersionCommandString, nil, &version) if err != nil { return "", fmt.Errorf("error getting version: %w", err) } diff --git a/shared/templates/service.go b/shared/templates/service.go index 37e4ea01..eb66ac03 100644 --- a/shared/templates/service.go +++ b/shared/templates/service.go @@ -1,13 +1,27 @@ package templates import ( + "context" "fmt" + "os" + "path/filepath" "strings" + "github.com/nodeset-org/hyperdrive/shared" + "github.com/nodeset-org/hyperdrive/shared/adapter" + "github.com/nodeset-org/hyperdrive/modules" modconfig "github.com/nodeset-org/hyperdrive/modules/config" ) +const ( + CallConfigFunctionCommandString string = adapter.HyperdriveModuleCommand + " call-config-function" +) + +type CallConfigFunctionResponse struct { + Result string `json:"result"` +} + // The data source for module service templates type ServiceDataSource struct { // Public parameters @@ -61,6 +75,41 @@ func (t *ServiceDataSource) GetValueArray(fqpn string, delimiter string) ([]stri return strings.Split(val, delimiter), nil } +func (t *ServiceDataSource) CallConfigFunction(funcName string) (string, error) { + moduleDir := t.ModuleConfigDir + adapterKeyPath := filepath.Join(moduleDir, shared.SecretsDir, shared.AdapterKeyFile) + bytes, err := os.ReadFile(adapterKeyPath) + + containerName := fmt.Sprintf("%s_%s_adapter", t.ModuleComposeProject, t.moduleInfo.Descriptor.Shortcut) + c, err := adapter.NewAdapterClient(string(containerName), string(bytes)) + if err != nil { + return "", fmt.Errorf("error creating adapter client: %w", err) + } + + modules := map[string]any{} + for fqmn, modSettings := range t.moduleSettingsMap { + modules[fqmn] = map[string]any{ + "settings": modSettings.SerializeToMap(), + } + } + + settings := map[string]any{ + "modules": modules, + } + + req := map[string]any{ + "funcName": funcName, + "settings": settings, + } + var response CallConfigFunctionResponse + err = adapter.RunCommand( + c, context.Background(), CallConfigFunctionCommandString, &req, &response) + if err != nil { + return "", fmt.Errorf("error calling config function \"%s\": %w", funcName, err) + } + return response.Result, nil +} + // Get the value of a property from its fully qualified path name func (t *ServiceDataSource) getPropertyValue(fqpn string) (string, error) { fqmn := "" diff --git a/specs/examples/hello-world/templates/service.tmpl b/specs/examples/hello-world/templates/service.tmpl index 8df9eb18..f23284fe 100644 --- a/specs/examples/hello-world/templates/service.tmpl +++ b/specs/examples/hello-world/templates/service.tmpl @@ -4,7 +4,7 @@ services: {{.GetValue serviceContainerName}}: image: {{.GetValue serviceContainerTag}} - container_name: {{.GetValue "nodeset/hyperdrive:projectName"}}_{{.GetValue serviceContainerName}} # Container names should follow the format "_" + container_name: {{.GetValue "nodeset/hyperdrive:projectName"}}_{{.GetValue serviceContainerName}} # Container names should follow the format "_" restart: unless-stopped ports: - "127.0.0.1:{{.GetValue apiPort}}:{{.GetValue apiPort}}/tcp" # Restricted to localhost outside of Docker @@ -30,6 +30,8 @@ services: - "{{.ModuleJwtKeyFile}}/{{.ModuleJwtKeyFile}}" # The JWT secret for the module's server - --hd-api-key - "{{.HyperdriveJwtKeyFile}}/{{.HyperdriveJwtKeyFile}}" # The JWT secret for the Hyperdrive client + - --custom-derived-value + - "{{.CallConfigFunction GetDerivedValue}}" # A custom value derived from the module's config networks: - net {{- range $network := .GetValueArray "nodeset/hyperdrive:additionalDockerNetworks" ","}} diff --git a/specs/modules/adapter.md b/specs/modules/adapter.md index f1d901d9..0b0ffbd1 100644 --- a/specs/modules/adapter.md +++ b/specs/modules/adapter.md @@ -33,7 +33,7 @@ Adapters are executed in one of two different modes: 1. Global mode 1. Project mode -When a module is installed, Hyperdrive will create and run one instance of your adapter's Docker container in **global mode**. This container is not tied to any one Hyperdrive project; all Hyperdrive installations on the node will all interact with it to use your adapter. Global mode commands run independently from individual Hyperdrive projects and are not affected by a project's configuration. They will *not* modify the behavior of your module and thus will not interact with your module's service containers; they are effectively **read-only** commands that will only access things within the adapter itself. Examples include getting the adapter's version, validating a pending configuration, and so on. +When a module is installed, Hyperdrive will create and run one instance of your adapter's Docker container in **global mode**. This container is not tied to any one Hyperdrive project; all Hyperdrive installations on the node will all interact with it to use your adapter. Global mode commands run independently from individual Hyperdrive projects and are not affected by a project's configuration. They will *not* modify the behavior of your module and thus will not interact with your module's service containers; they are effectively **read-only** commands that will only access things within the adapter itself. Examples include getting the adapter's version, validating a pending configuration, and so on. Once the user configures a Hyperdrive project, the system will create a *second* instance of your adapter's Docker container. This one will be provided with all of the project-specific details, such as the paths for the configuration and log directories, and the path for the authentication key file (discussed later). Project mode commands should be considered **read and write**, because they can be used to interact with your module's services and modify its configuration. @@ -200,7 +200,7 @@ The following serialized JSON object: - `ports` (object, required): A mapping for externally available TCP/UDP ports that your module's services will bind when running. Each property in the object must have the FQMN of one of your module's properties as its name, and the port value as its value. This is used by Hyperdrive to ensure that your service won't bind ports that are already in use by other services. If your ports are not externally bound, and restricted to Docker's internal network, they don't need to be listed here. This list can be empty if `errors` is not empty for simplicity. - `servicesToRestart` (string[], required): A list of Docker container service IDs (as written in your module's [service templates](./module.md#packages)) that need to be restarted (if already running) for these settings to take effect. This will be displayed to the user for informational purposes, but Hyperdrive will not actually restart these containers as part of issuing this command. Your adapter doesn't need to check whether or not the service is currently running; it can simply report that a service restart is required even if the service is stopped or doesn't exist. -For example:iii +For example: ```json { @@ -209,7 +209,7 @@ For example:iii ], "ports": { "publicApiPort": 1234, - "serverListenerPort": 5678, + "serverListenerPort": 5678, }, "servicesToRestart": [ "my-service", @@ -257,7 +257,7 @@ where: ### `hd-module start` -*NOTE: this command is currently a WIP and designed for MVP purposes only. The final form is expected to change.* +*NOTE: this command is currently a WIP and designed for MVP purposes only. The final form is expected to change.* Hyperdrive calls this command after your module's configuration settings have been saved with `set-settings`. Your adapter should start (or restart) whatever Docker containers it needs to based on the current settings (which will be provided with the call). For MVP purposes your adapter should execute a `docker compose up` command with the relevant files passed in based on the provided settings. Your module's service file templates will be instantiated and placed into the `HD_COMPOSE_DIR` directory prior to this call. It should use Docker Compose to start the services; for the Compose project name, use the `HD_COMPOSE_PROJECT` property. @@ -320,4 +320,36 @@ where: #### Output -This should output whatever output your command has; it will be viewed directly by the user so it doesn't need to be in JSON format. Any errors that occur should be printed to `STDERR`. \ No newline at end of file +This should output whatever output your command has; it will be viewed directly by the user so it doesn't need to be in JSON format. Any errors that occur should be printed to `STDERR`. + + +### `hd-module call-config-function` + +This is called when the user wants to run a command on your adapter to dynamically compute values for configuration/template substitutions. + + +#### Input + +```json +{ + "funcName": "...", + "settings": "...", +} +``` + +where: + + - `funcName` is the name of the adapter-defined function to invoke. + - `settings` is the full Hyperdrive Settings object, passed to the global adapter so it can read any relevant module values. + +#### Output + +```json +{ + "result": "...", +} +``` + +where: + + - `result` is the string containing the returned computed value. diff --git a/specs/modules/templates.md b/specs/modules/templates.md index c4b5a9e5..84405fc4 100644 --- a/specs/modules/templates.md +++ b/specs/modules/templates.md @@ -115,7 +115,7 @@ Any dynamic property templates will be run dynamically whenever one of the follo ### UseDefault -`{{.UseDefault}}` can be used within the `template` of a dynamic property to indicate that Hyperdrive should use its `default` value. This is helpful to reduce duplication if your default value ever changes, so you don't have to set it multiple times. +`{{.UseDefault}}` can be used within the `template` of a dynamic property to indicate that Hyperdrive should use its `default` value. This is helpful to reduce duplication if your default value ever changes, so you don't have to set it multiple times. ## Service Docker Compose Templates @@ -151,15 +151,19 @@ Whenever Hyperdrive starts its services (including the modules), the template fi `{{.GetValueArray }}` takes the value of the provided parameter, which is specified by its [Fully Qualified Parameter Name](), splits it according to the `delimiter` string, and returns the resulting array. This is useful to take parameters that represent multiple values separated by a comma, semicolon, or other delimiter, and split them into an explicit array so they can be iterated on in a template via the `for` keyword. +### CallConfigFunction + +`{{.CallConfigFunction }}` allows you to invoke a custom function implemented in the module adapter. This enables powerful, reusable logic like arithmetic or dynamic derivation of values that are too complex for regular templating expressions. + ### ModuleConfigDir -` {{.ModuleConfigDir}}` returns the full path of the directory that stores your service's configuration, as provided by the adapter during a `set-settings` operation. +`{{.ModuleConfigDir}}` returns the full path of the directory that stores your service's configuration, as provided by the adapter during a `set-settings` operation. ### ModuleLogDir -` {{.ModuleLogDir}}` returns the full path of the directory that stores your module's log files. +`{{.ModuleLogDir}}` returns the full path of the directory that stores your module's log files. ### ModuleDataDir