mirror of
https://github.com/holos-run/holos.git
synced 2026-03-20 09:15:02 +00:00
This patch addresses Nate's feedback that it's difficult to know what platform is being operated on. Previously it wasn't clear where the platform id used for push and pull comes from. The source of truth is the platform.metadata.json file created when the platform is first generated using `holos generate platform k3d`. This patch removes the platformId field from the platform.config.json file, renames the platform.config.json file to platform.model.json and renames the internal symbols to match the domain language of "Platform Model" instead of the less clear "config" This patch also changes the API between holos and CUE to use the proto json imported from the proto file instead of generated from the go code generated from the proto file. The purpose is to ensure protojson encoding is used end to end. Default log handler: The patch also changes the default log output to print only the message to stderr. This addresses similar feedback from both Gary and Nate that the output is skipped over because it feels like internal debug logs. We still want 100% of output to go through the logger so we can ensure each line can be made into valid json. Info messages however are meant for the user and all other attributes can be stripped off by default. If additional source location is necessary, enable the text or json output format. Protobuf JSON: This patch modifies the API contract between holos and CUE to ensure data is exchanged exclusively using protojson. This is necessary because protobuf has a canonical json format which is not compatible with the go json package struct tags. When Holos handles a protobuf message, it must marshal and unmarshal it using the protojson package. Similarly, when importing protobuf messages into CUE, we must use `cue import` instead of `cue go get` so that the canonical format is used instead of the invalid go json struct tags. Finally, when a Go struct like v1alpha1.Form is used to represent data defined in cue which contains a nested protobuf message, Holos should use a cue.Value to lookup the nested path, marshal it into json bytes, then unmarshal it again using protojson.
73 lines
2.8 KiB
Go
73 lines
2.8 KiB
Go
package client
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/holos-run/holos/internal/server/middleware/logger"
|
|
object "github.com/holos-run/holos/service/gen/holos/object/v1alpha1"
|
|
platform "github.com/holos-run/holos/service/gen/holos/platform/v1alpha1"
|
|
"google.golang.org/protobuf/encoding/protojson"
|
|
)
|
|
|
|
// PlatformMetadataFile is the platform metadata json file name located in the
|
|
// root of a platform directory. This file is the authoritative source of truth
|
|
// for the PlatformID used in rpc calls to the PlatformService.
|
|
const PlatformMetadataFile = "platform.metadata.json"
|
|
|
|
// PlatformConfigFile represents the marshaled json representation of the
|
|
// PlatformConfig DTO used to persist the inputs to the CUE platform code.
|
|
const PlatformConfigFile = "platform.config.json"
|
|
|
|
// LoadPlatformMetadata loads the platform.metadata.json file from a named path.
|
|
// Used as the authoritative source of truth to obtain a platform id for
|
|
// PlatformService rpc methods.
|
|
func LoadPlatformMetadata(ctx context.Context, name string) (*platform.Platform, error) {
|
|
data, err := os.ReadFile(filepath.Join(name, PlatformMetadataFile))
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not load platform metadata: %w", err)
|
|
}
|
|
p := &platform.Platform{}
|
|
if err := protojson.Unmarshal(data, p); err != nil {
|
|
return nil, fmt.Errorf("could not load platform metadata: %w", err)
|
|
}
|
|
log := logger.FromContext(ctx)
|
|
log.DebugContext(ctx, "loaded: "+p.GetName(), "path", PlatformMetadataFile, "name", p.GetName(), "display_name", p.GetDisplayName(), "id", p.GetId())
|
|
return p, nil
|
|
}
|
|
|
|
// LoadPlatformConfig loads the PlatformConfig DTO from the platform.config.json
|
|
// file. Useful to provide all values necessary to render cue config without an
|
|
// rpc to the HolosService.
|
|
func LoadPlatformConfig(ctx context.Context, name string) (*object.PlatformConfig, error) {
|
|
data, err := os.ReadFile(filepath.Join(name, PlatformConfigFile))
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not load platform model: %w", err)
|
|
}
|
|
p := &object.PlatformConfig{}
|
|
if err := protojson.Unmarshal(data, p); err != nil {
|
|
return nil, fmt.Errorf("could not load platform model: %w", err)
|
|
}
|
|
return p, nil
|
|
}
|
|
|
|
// SavePlatformConfig writes pc to the platform root directory path identified by name.
|
|
func SavePlatformConfig(ctx context.Context, name string, pc *object.PlatformConfig) (string, error) {
|
|
encoder := protojson.MarshalOptions{Multiline: true}
|
|
data, err := encoder.Marshal(pc)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if len(data) > 0 {
|
|
data = append(data, '\n')
|
|
}
|
|
path := filepath.Join(name, PlatformConfigFile)
|
|
if err := os.WriteFile(path, data, 0644); err != nil {
|
|
return "", fmt.Errorf("could not write platform config: %w", err)
|
|
}
|
|
logger.FromContext(ctx).DebugContext(ctx, "wrote", "path", path)
|
|
return path, nil
|
|
}
|