From 1df841bb542323adce92013cd55eb24ab238a1dc Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Tue, 14 Mar 2023 14:33:11 +0400 Subject: [PATCH] refactor: change the interface of META Use a global instance, handle loading/saving META in global context. Deprecate legacy syslinux ADV, provide an easier interface for consumers. Expose META as resources. Fix the bootloader revert process (it was completely broken for quite a while :sad:). This is a first step which mostly does preparation work, real changes will come in the next PRs: * add APIs to write to META * consume META keys for platform network config for `metal` * custom key for URL `${code}` Signed-off-by: Andrey Smirnov --- .../definitions/runtime/runtime.proto | 5 + cmd/installer/pkg/install/install.go | 13 +- .../server/v1alpha1/v1alpha1_server.go | 36 +- internal/app/machined/main.go | 14 - internal/app/machined/pkg/runtime/state.go | 12 + .../pkg/runtime/v1alpha1/bootloader/meta.go | 137 ------- .../runtime/v1alpha1/v1alpha1_sequencer.go | 15 + .../v1alpha1/v1alpha1_sequencer_tasks.go | 55 +-- .../pkg/runtime/v1alpha1/v1alpha1_state.go | 149 ++++++-- .../pkg/runtime/v1alpha2/v1alpha2_state.go | 1 + .../app/machined/pkg/system/services/etcd.go | 18 +- internal/app/machined/revert.go | 114 ++++++ internal/pkg/meta/constants.go | 16 + .../meta/internal}/adv/adv.go | 15 +- .../meta/internal}/adv/syslinux/syslinux.go | 35 +- .../internal}/adv/syslinux/syslinux_test.go | 21 +- .../internal}/adv/syslinux/testdata/adv.sys | Bin .../meta/internal}/adv/talos/talos.go | 14 +- .../meta/internal}/adv/talos/talos_test.go | 9 +- internal/pkg/meta/meta.go | 341 ++++++++++++++++++ internal/pkg/meta/meta_test.go | 98 +++++ .../definitions/runtime/runtime.pb.go | 169 ++++++--- .../definitions/runtime/runtime_vtproto.pb.go | 137 +++++++ .../resources/runtime/deep_copy.generated.go | 8 +- pkg/machinery/resources/runtime/meta_key.go | 62 ++++ pkg/machinery/resources/runtime/runtime.go | 2 +- .../resources/runtime/runtime_test.go | 1 + website/content/v1.4/reference/api.md | 16 + 28 files changed, 1188 insertions(+), 325 deletions(-) delete mode 100644 internal/app/machined/pkg/runtime/v1alpha1/bootloader/meta.go create mode 100644 internal/app/machined/revert.go create mode 100644 internal/pkg/meta/constants.go rename internal/{app/machined/pkg/runtime/v1alpha1/bootloader => pkg/meta/internal}/adv/adv.go (64%) rename internal/{app/machined/pkg/runtime/v1alpha1/bootloader => pkg/meta/internal}/adv/syslinux/syslinux.go (88%) rename internal/{app/machined/pkg/runtime/v1alpha1/bootloader => pkg/meta/internal}/adv/syslinux/syslinux_test.go (99%) rename internal/{app/machined/pkg/runtime/v1alpha1/bootloader => pkg/meta/internal}/adv/syslinux/testdata/adv.sys (100%) rename internal/{app/machined/pkg/runtime/v1alpha1/bootloader => pkg/meta/internal}/adv/talos/talos.go (93%) rename internal/{app/machined/pkg/runtime/v1alpha1/bootloader => pkg/meta/internal}/adv/talos/talos_test.go (83%) create mode 100644 internal/pkg/meta/meta.go create mode 100644 internal/pkg/meta/meta_test.go create mode 100644 pkg/machinery/resources/runtime/meta_key.go diff --git a/api/resource/definitions/runtime/runtime.proto b/api/resource/definitions/runtime/runtime.proto index 5c9fffe99..89c2329ce 100755 --- a/api/resource/definitions/runtime/runtime.proto +++ b/api/resource/definitions/runtime/runtime.proto @@ -37,6 +37,11 @@ message MachineStatusStatus { repeated UnmetCondition unmet_conditions = 2; } +// MetaKeySpec describes status of the defined sysctls. +message MetaKeySpec { + string value = 1; +} + // MountStatusSpec describes status of the defined sysctls. message MountStatusSpec { string source = 1; diff --git a/cmd/installer/pkg/install/install.go b/cmd/installer/pkg/install/install.go index 1031eb662..768f5fe65 100644 --- a/cmd/installer/pkg/install/install.go +++ b/cmd/installer/pkg/install/install.go @@ -16,8 +16,8 @@ import ( "github.com/siderolabs/talos/internal/app/machined/pkg/runtime" "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/board" "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader" - "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv" "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader/grub" + "github.com/siderolabs/talos/internal/pkg/meta" "github.com/siderolabs/talos/internal/pkg/mount" "github.com/siderolabs/talos/pkg/machinery/constants" "github.com/siderolabs/talos/pkg/machinery/kernel" @@ -323,20 +323,19 @@ func (i *Installer) Install(seq runtime.Sequence) (err error) { } if seq == runtime.SequenceUpgrade { - var meta *bootloader.Meta + var metaState *meta.Meta - if meta, err = bootloader.NewMeta(); err != nil { + if metaState, err = meta.New(context.Background(), nil); err != nil { return err } - //nolint:errcheck - defer meta.Close() + var ok bool - if ok := meta.LegacyADV.SetTag(adv.Upgrade, string(i.Current)); !ok { + if ok, err = metaState.SetTag(context.Background(), meta.Upgrade, string(i.Current)); !ok || err != nil { return fmt.Errorf("failed to set upgrade tag: %q", i.Current) } - if err = meta.Write(); err != nil { + if err = metaState.Flush(); err != nil { return err } } diff --git a/internal/app/machined/internal/server/v1alpha1/v1alpha1_server.go b/internal/app/machined/internal/server/v1alpha1/v1alpha1_server.go index f6dff928b..0ddf2facd 100644 --- a/internal/app/machined/internal/server/v1alpha1/v1alpha1_server.go +++ b/internal/app/machined/internal/server/v1alpha1/v1alpha1_server.go @@ -55,8 +55,6 @@ import ( installer "github.com/siderolabs/talos/cmd/installer/pkg/install" "github.com/siderolabs/talos/internal/app/machined/pkg/runtime" "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/disk" - "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader" - "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv" "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader/grub" "github.com/siderolabs/talos/internal/app/machined/pkg/system" "github.com/siderolabs/talos/internal/app/resources" @@ -67,6 +65,7 @@ import ( "github.com/siderolabs/talos/internal/pkg/containers/cri" "github.com/siderolabs/talos/internal/pkg/etcd" "github.com/siderolabs/talos/internal/pkg/install" + "github.com/siderolabs/talos/internal/pkg/meta" "github.com/siderolabs/talos/internal/pkg/miniprocfs" "github.com/siderolabs/talos/internal/pkg/mount" "github.com/siderolabs/talos/pkg/archiver" @@ -474,14 +473,14 @@ func (s *Server) Shutdown(ctx context.Context, in *machine.ShutdownRequest) (rep // Upgrade initiates an upgrade. // //nolint:gocyclo,cyclop -func (s *Server) Upgrade(ctx context.Context, in *machine.UpgradeRequest) (reply *machine.UpgradeResponse, err error) { +func (s *Server) Upgrade(ctx context.Context, in *machine.UpgradeRequest) (*machine.UpgradeResponse, error) { actorID := uuid.New().String() var mu *concurrency.Mutex ctx = context.WithValue(ctx, runtime.ActorIDCtxKey{}, actorID) - if err = s.checkSupported(runtime.Upgrade); err != nil { + if err := s.checkSupported(runtime.Upgrade); err != nil { return nil, err } @@ -489,7 +488,7 @@ func (s *Server) Upgrade(ctx context.Context, in *machine.UpgradeRequest) (reply log.Printf("validating %q", in.GetImage()) - if err = install.PullAndValidateInstallerImage(ctx, s.Controller.Runtime().Config().Machine().Registries(), in.GetImage()); err != nil { + if err := install.PullAndValidateInstallerImage(ctx, s.Controller.Runtime().Config().Machine().Registries(), in.GetImage()); err != nil { return nil, fmt.Errorf("error validating installer image %q: %w", in.GetImage(), err) } @@ -518,19 +517,12 @@ func (s *Server) Upgrade(ctx context.Context, in *machine.UpgradeRequest) (reply runCtx := context.WithValue(context.Background(), runtime.ActorIDCtxKey{}, actorID) if in.GetStage() { - meta, err := bootloader.NewMeta() - if err != nil { - return nil, fmt.Errorf("error reading meta: %w", err) - } - //nolint:errcheck - defer meta.Close() - - if !meta.ADV.SetTag(adv.StagedUpgradeImageRef, in.GetImage()) { - return nil, fmt.Errorf("error adding staged upgrade image ref tag") + if ok, err := s.Controller.Runtime().State().Machine().Meta().SetTag(ctx, meta.StagedUpgradeImageRef, in.GetImage()); !ok || err != nil { + return nil, fmt.Errorf("error adding staged upgrade image ref tag: %w", err) } opts := install.DefaultInstallOptions() - if err = opts.Apply(install.OptionsFromUpgradeRequest(s.Controller.Runtime(), in)...); err != nil { + if err := opts.Apply(install.OptionsFromUpgradeRequest(s.Controller.Runtime(), in)...); err != nil { return nil, fmt.Errorf("error applying install options: %w", err) } @@ -539,11 +531,13 @@ func (s *Server) Upgrade(ctx context.Context, in *machine.UpgradeRequest) (reply return nil, fmt.Errorf("error serializing install options: %s", err) } - if !meta.ADV.SetTag(adv.StagedUpgradeInstallOptions, string(serialized)) { - return nil, fmt.Errorf("error adding staged upgrade install options tag") + var ok bool + + if ok, err = s.Controller.Runtime().State().Machine().Meta().SetTag(ctx, meta.StagedUpgradeInstallOptions, string(serialized)); !ok || err != nil { + return nil, fmt.Errorf("error adding staged upgrade install options tag: %w", err) } - if err = meta.Write(); err != nil { + if err = s.Controller.Runtime().State().Machine().Meta().Flush(); err != nil { return nil, fmt.Errorf("error writing meta: %w", err) } @@ -572,16 +566,14 @@ func (s *Server) Upgrade(ctx context.Context, in *machine.UpgradeRequest) (reply }() } - reply = &machine.UpgradeResponse{ + return &machine.UpgradeResponse{ Messages: []*machine.Upgrade{ { Ack: "Upgrade request received", ActorId: actorID, }, }, - } - - return reply, nil + }, nil } // ResetOptions implements runtime.ResetOptions interface. diff --git a/internal/app/machined/main.go b/internal/app/machined/main.go index 4aaf791ae..0b88b709b 100644 --- a/internal/app/machined/main.go +++ b/internal/app/machined/main.go @@ -27,7 +27,6 @@ import ( "github.com/siderolabs/talos/internal/app/dashboard" "github.com/siderolabs/talos/internal/app/machined/pkg/runtime" v1alpha1runtime "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1" - "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader" "github.com/siderolabs/talos/internal/app/machined/pkg/system" "github.com/siderolabs/talos/internal/app/machined/pkg/system/services" "github.com/siderolabs/talos/internal/app/maintenance" @@ -61,19 +60,6 @@ func recovery() { } } -func revertBootloader() { - if meta, err := bootloader.NewMeta(); err == nil { - if err = meta.Revert(); err != nil { - log.Printf("failed to revert upgrade: %v", err) - } - - //nolint:errcheck - meta.Close() - } else { - log.Printf("failed to open meta: %v", err) - } -} - // syncNonVolatileStorageBuffers invokes unix.Sync and waits up to 30 seconds // for it to finish. // diff --git a/internal/app/machined/pkg/runtime/state.go b/internal/app/machined/pkg/runtime/state.go index a5fae2483..412d6c1b2 100644 --- a/internal/app/machined/pkg/runtime/state.go +++ b/internal/app/machined/pkg/runtime/state.go @@ -40,6 +40,18 @@ type MachineState interface { KexecPrepared(bool) IsKexecPrepared() bool DBus() DBusState + Meta() Meta +} + +// Meta defines the access to META partition. +type Meta interface { + ReadTag(t uint8) (val string, ok bool) + ReadTagBytes(t uint8) (val []byte, ok bool) + SetTag(ctx context.Context, t uint8, val string) (bool, error) + SetTagBytes(ctx context.Context, t uint8, val []byte) (bool, error) + DeleteTag(ctx context.Context, t uint8) (bool, error) + Reload(ctx context.Context) error + Flush() error } // ClusterState defines the cluster state. diff --git a/internal/app/machined/pkg/runtime/v1alpha1/bootloader/meta.go b/internal/app/machined/pkg/runtime/v1alpha1/bootloader/meta.go deleted file mode 100644 index 45a230a88..000000000 --- a/internal/app/machined/pkg/runtime/v1alpha1/bootloader/meta.go +++ /dev/null @@ -1,137 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -package bootloader - -import ( - "fmt" - "io" - "os" - - "github.com/siderolabs/go-blockdevice/blockdevice/probe" - - "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv" - "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv/syslinux" - "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv/talos" - "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader/grub" - "github.com/siderolabs/talos/pkg/machinery/constants" -) - -// Meta represents the meta reader. -type Meta struct { - *os.File - LegacyADV adv.ADV - ADV adv.ADV -} - -// NewMeta initializes and returns a `Meta`. -func NewMeta() (meta *Meta, err error) { - var ( - f *os.File - dev *probe.ProbedBlockDevice - ) - - dev, err = probe.GetDevWithPartitionName(constants.MetaPartitionLabel) - if err != nil { - return nil, err - } - - part, err := dev.OpenPartition(constants.MetaPartitionLabel) - if err != nil { - return nil, err - } - - f = part.Device() - - adv, err := talos.NewADV(f) - if adv == nil && err != nil { - // if adv is not nil, but err is nil, it might be missing ADV, ignore it - return nil, err - } - - legacyAdv, err := syslinux.NewADV(f) - if err != nil { - return nil, err - } - - return &Meta{ - File: f, - LegacyADV: legacyAdv, - ADV: adv, - }, nil -} - -func (m *Meta) Write() error { - serialized, err := m.ADV.Bytes() - if err != nil { - return err - } - - n, err := m.File.WriteAt(serialized, 0) - if err != nil { - return err - } - - if n != len(serialized) { - return fmt.Errorf("expected to write %d bytes, wrote %d", len(serialized), n) - } - - serialized, err = m.LegacyADV.Bytes() - if err != nil { - return err - } - - offset, err := m.File.Seek(-int64(len(serialized)), io.SeekEnd) - if err != nil { - return err - } - - n, err = m.File.WriteAt(serialized, offset) - if err != nil { - return err - } - - if n != len(serialized) { - return fmt.Errorf("expected to write %d bytes, wrote %d", len(serialized), n) - } - - return m.File.Sync() -} - -// Revert reverts the default bootloader label to the previous installation. -func (m *Meta) Revert() (err error) { - label, ok := m.LegacyADV.ReadTag(adv.Upgrade) - if !ok { - return nil - } - - if label == "" { - m.LegacyADV.DeleteTag(adv.Upgrade) - - return m.Write() - } - - conf, err := grub.Read(grub.ConfigPath) - if err != nil { - return err - } - - if conf == nil { - return nil - } - - bootEntry, err := grub.ParseBootLabel(label) - if err != nil { - return err - } - - conf.Default = bootEntry - if err = conf.Write(grub.ConfigPath); err != nil { - return err - } - - m.LegacyADV.DeleteTag(adv.Upgrade) - - return m.Write() -} diff --git a/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_sequencer.go b/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_sequencer.go index 1d7a632ce..71ced0fe5 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_sequencer.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_sequencer.go @@ -109,6 +109,9 @@ func (*Sequencer) Initialize(r runtime.Runtime) []runtime.Phase { "earlyServices", StartUdevd, StartMachined, + ).Append( + "meta", + ReloadMeta, ).AppendWithDeferredCheck( func() bool { disabledStr := procfs.ProcCmdline().Get(constants.KernelParamDashboardDisabled).First() @@ -168,6 +171,12 @@ func (*Sequencer) Install(r runtime.Runtime) []runtime.Phase { ).Append( "install", Install, + ).Append( + "meta", + ReloadMeta, + ).Append( + "saveMeta", // saving META here to merge in-memory changes with the on-disk ones from the installer + FlushMeta, ).Append( "saveStateEncryptionConfig", SaveStateEncryptionConfig, @@ -455,6 +464,9 @@ func (*Sequencer) MaintenanceUpgrade(r runtime.Runtime, _ *machineapi.UpgradeReq ).Append( "upgrade", Upgrade, + ).Append( + "meta", + ReloadMeta, ).Append( "mountBoot", MountBootPartition, @@ -526,6 +538,9 @@ func (*Sequencer) Upgrade(r runtime.Runtime, in *machineapi.UpgradeRequest) []ru ).Append( "upgrade", Upgrade, + ).Append( + "meta", + ReloadMeta, ).Append( "mountBoot", MountBootPartition, diff --git a/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_sequencer_tasks.go b/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_sequencer_tasks.go index c6fff0dc9..6f4e4a862 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_sequencer_tasks.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_sequencer_tasks.go @@ -46,8 +46,6 @@ import ( installer "github.com/siderolabs/talos/cmd/installer/pkg/install" "github.com/siderolabs/talos/internal/app/machined/pkg/runtime" - "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader" - "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv" "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader/grub" "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/platform" perrors "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/platform/errors" @@ -59,6 +57,7 @@ import ( "github.com/siderolabs/talos/internal/pkg/cri" "github.com/siderolabs/talos/internal/pkg/etcd" "github.com/siderolabs/talos/internal/pkg/install" + "github.com/siderolabs/talos/internal/pkg/meta" "github.com/siderolabs/talos/internal/pkg/mount" "github.com/siderolabs/talos/internal/pkg/partition" "github.com/siderolabs/talos/pkg/conditions" @@ -1954,17 +1953,15 @@ func LabelNodeAsControlPlane(runtime.Sequence, any) (runtime.TaskExecutionFunc, // UpdateBootloader represents the UpdateBootloader task. func UpdateBootloader(runtime.Sequence, any) (runtime.TaskExecutionFunc, string) { return func(ctx context.Context, logger *log.Logger, r runtime.Runtime) (err error) { - meta, err := bootloader.NewMeta() + ok, err := r.State().Machine().Meta().DeleteTag(ctx, meta.Upgrade) if err != nil { return err } - //nolint:errcheck - defer meta.Close() - if ok := meta.LegacyADV.DeleteTag(adv.Upgrade); ok { + if ok { logger.Println("removing fallback") - if err = meta.Write(); err != nil { + if err = r.State().Machine().Meta().Flush(); err != nil { return err } } @@ -2031,24 +2028,22 @@ func SaveStateEncryptionConfig(runtime.Sequence, any) (runtime.TaskExecutionFunc return nil } - meta, err := bootloader.NewMeta() - if err != nil { - return err - } - //nolint:errcheck - defer meta.Close() - var data []byte if data, err = json.Marshal(encryption); err != nil { return err } - if !meta.ADV.SetTagBytes(adv.StateEncryptionConfig, data) { + ok, err := r.State().Machine().Meta().SetTagBytes(ctx, meta.StateEncryptionConfig, data) + if err != nil { + return err + } + + if !ok { return fmt.Errorf("failed to save state encryption config in the META partition") } - return meta.Write() + return r.State().Machine().Meta().Flush() }, "SaveStateEncryptionConfig" } @@ -2083,13 +2078,6 @@ func UnmountEFIPartition(runtime.Sequence, any) (runtime.TaskExecutionFunc, stri // MountStatePartition mounts the system partition. func MountStatePartition(seq runtime.Sequence, _ any) (runtime.TaskExecutionFunc, string) { return func(ctx context.Context, logger *log.Logger, r runtime.Runtime) (err error) { - meta, err := bootloader.NewMeta() - if err != nil { - return err - } - //nolint:errcheck - defer meta.Close() - flags := mount.SkipIfMounted if seq == runtime.SequenceInitialize { @@ -2109,7 +2097,7 @@ func MountStatePartition(seq runtime.Sequence, _ any) (runtime.TaskExecutionFunc if encryption == nil { var encryptionFromMeta *v1alpha1.EncryptionConfig - data, ok := meta.ADV.ReadTagBytes(adv.StateEncryptionConfig) + data, ok := r.State().Machine().Meta().ReadTagBytes(meta.StateEncryptionConfig) if ok { if err = json.Unmarshal(data, &encryptionFromMeta); err != nil { return err @@ -2409,6 +2397,25 @@ func CleanupLegacyStaticPodFiles(runtime.Sequence, any) (runtime.TaskExecutionFu }, "cleanupLegacyStaticPodFiles" } +// ReloadMeta reloads META partition after disk mount, installer run, etc. +func ReloadMeta(runtime.Sequence, any) (runtime.TaskExecutionFunc, string) { + return func(ctx context.Context, logger *log.Logger, r runtime.Runtime) error { + err := r.State().Machine().Meta().Reload(ctx) + if err != nil && !os.IsNotExist(err) { + return err + } + + return nil + }, "reloadMeta" +} + +// FlushMeta flushes META partition after install run. +func FlushMeta(runtime.Sequence, any) (runtime.TaskExecutionFunc, string) { + return func(ctx context.Context, logger *log.Logger, r runtime.Runtime) error { + return r.State().Machine().Meta().Flush() + }, "flushMeta" +} + func pauseOnFailure(callback func(runtime.Sequence, any) (runtime.TaskExecutionFunc, string), timeout time.Duration, ) func(seq runtime.Sequence, data any) (runtime.TaskExecutionFunc, string) { diff --git a/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_state.go b/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_state.go index d5ca3d44e..ff4f5e807 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_state.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_state.go @@ -5,18 +5,21 @@ package v1alpha1 import ( + "context" "errors" + "log" "os" + "sync" + "github.com/cosi-project/runtime/pkg/state" multierror "github.com/hashicorp/go-multierror" "github.com/siderolabs/go-blockdevice/blockdevice/probe" "github.com/siderolabs/talos/internal/app/machined/pkg/runtime" "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/disk" - "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader" - "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv" "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/platform" "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha2" + "github.com/siderolabs/talos/internal/pkg/meta" "github.com/siderolabs/talos/pkg/machinery/constants" ) @@ -30,10 +33,14 @@ type State struct { // MachineState represents the machine's state. type MachineState struct { - platform runtime.Platform + platform runtime.Platform + resources state.State disks map[string]*probe.ProbedBlockDevice + meta *meta.Meta + metaOnce sync.Once + stagedInstall bool stagedInstallImageRef string stagedInstallOptions []byte @@ -53,8 +60,14 @@ func NewState() (s *State, err error) { return nil, err } + v2State, err := v1alpha2.NewState() + if err != nil { + return nil, err + } + machine := &MachineState{ - platform: p, + platform: p, + resources: v2State.Resources(), } err = machine.probeDisks() @@ -64,15 +77,8 @@ func NewState() (s *State, err error) { } } - machine.probeMeta() - cluster := &ClusterState{} - v2State, err := v1alpha2.NewState() - if err != nil { - return nil, err - } - s = &State{ platform: p, cluster: cluster, @@ -134,30 +140,114 @@ func (s *MachineState) probeDisks(labels ...string) error { return nil } -func (s *MachineState) probeMeta() { +// Meta implements the runtime.MachineState interface. +func (s *MachineState) Meta() runtime.Meta { + // no META in container mode if s.platform.Mode() == runtime.ModeContainer { - return + return s } - meta, err := bootloader.NewMeta() - if err != nil { - // ignore missing meta - return + var justLoaded bool + + s.metaOnce.Do(func() { + var err error + + s.meta, err = meta.New(context.Background(), s.resources) + if err != nil { + log.Printf("META: failed to load: %s", err) + } else { + s.probeMeta() + } + + justLoaded = true + }) + + return metaWrapper{ + MachineState: s, + justLoaded: justLoaded, + } +} + +// ReadTag implements the runtime.Meta interface. +func (s *MachineState) ReadTag(t uint8) (val string, ok bool) { + if s.platform.Mode() == runtime.ModeContainer { + return "", false } - defer meta.Close() //nolint:errcheck + return s.meta.ReadTag(t) +} - stagedInstallImageRef, ok1 := meta.ADV.ReadTag(adv.StagedUpgradeImageRef) - stagedInstallOptions, ok2 := meta.ADV.ReadTag(adv.StagedUpgradeInstallOptions) +// ReadTagBytes implements the runtime.Meta interface. +func (s *MachineState) ReadTagBytes(t uint8) (val []byte, ok bool) { + if s.platform.Mode() == runtime.ModeContainer { + return nil, false + } + + return s.meta.ReadTagBytes(t) +} + +// SetTag implements the runtime.Meta interface. +func (s *MachineState) SetTag(ctx context.Context, t uint8, val string) (bool, error) { + if s.platform.Mode() == runtime.ModeContainer { + return false, nil + } + + return s.meta.SetTag(ctx, t, val) +} + +// SetTagBytes implements the runtime.Meta interface. +func (s *MachineState) SetTagBytes(ctx context.Context, t uint8, val []byte) (bool, error) { + if s.platform.Mode() == runtime.ModeContainer { + return false, nil + } + + return s.meta.SetTagBytes(ctx, t, val) +} + +// DeleteTag implements the runtime.Meta interface. +func (s *MachineState) DeleteTag(ctx context.Context, t uint8) (bool, error) { + if s.platform.Mode() == runtime.ModeContainer { + return false, nil + } + + return s.meta.DeleteTag(ctx, t) +} + +// Reload implements the runtime.Meta interface. +func (s *MachineState) Reload(ctx context.Context) error { + if s.platform.Mode() == runtime.ModeContainer { + return nil + } + + err := s.meta.Reload(ctx) + if err == nil { + s.probeMeta() + } + + return err +} + +// Flush implements the runtime.Meta interface. +func (s *MachineState) Flush() error { + if s.platform.Mode() == runtime.ModeContainer { + return nil + } + + return s.meta.Flush() +} + +func (s *MachineState) probeMeta() { + stagedInstallImageRef, ok1 := s.meta.ReadTag(meta.StagedUpgradeImageRef) + stagedInstallOptions, ok2 := s.meta.ReadTag(meta.StagedUpgradeInstallOptions) s.stagedInstall = ok1 && ok2 if s.stagedInstall { // clear the staged install flags - meta.ADV.DeleteTag(adv.StagedUpgradeImageRef) - meta.ADV.DeleteTag(adv.StagedUpgradeInstallOptions) + _, err1 := s.meta.DeleteTag(context.Background(), meta.StagedUpgradeImageRef) + _, err2 := s.meta.DeleteTag(context.Background(), meta.StagedUpgradeInstallOptions) - if err = meta.Write(); err != nil { + if err := s.meta.Flush(); err != nil || err1 != nil || err2 != nil { // failed to delete staged install tags, clear the stagedInstall to prevent boot looping s.stagedInstall = false } @@ -236,3 +326,16 @@ func (s *MachineState) IsKexecPrepared() bool { func (s *MachineState) DBus() runtime.DBusState { return &s.dbus } + +type metaWrapper struct { + *MachineState + justLoaded bool +} + +func (m metaWrapper) Reload(ctx context.Context) error { + if m.justLoaded { + return nil + } + + return m.MachineState.Reload(ctx) +} diff --git a/internal/app/machined/pkg/runtime/v1alpha2/v1alpha2_state.go b/internal/app/machined/pkg/runtime/v1alpha2/v1alpha2_state.go index 9aa33b484..5d12d3ffe 100644 --- a/internal/app/machined/pkg/runtime/v1alpha2/v1alpha2_state.go +++ b/internal/app/machined/pkg/runtime/v1alpha2/v1alpha2_state.go @@ -165,6 +165,7 @@ func NewState() (*State, error) { &runtime.KernelParamDefaultSpec{}, &runtime.KernelParamStatus{}, &runtime.MachineStatus{}, + &runtime.MetaKey{}, &runtime.MountStatus{}, &runtime.PlatformMetadata{}, &secrets.API{}, diff --git a/internal/app/machined/pkg/system/services/etcd.go b/internal/app/machined/pkg/system/services/etcd.go index 1562dbf93..60c7c322f 100644 --- a/internal/app/machined/pkg/system/services/etcd.go +++ b/internal/app/machined/pkg/system/services/etcd.go @@ -30,8 +30,6 @@ import ( snapshot "go.etcd.io/etcd/etcdutl/v3/snapshot" "github.com/siderolabs/talos/internal/app/machined/pkg/runtime" - "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader" - "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv" "github.com/siderolabs/talos/internal/app/machined/pkg/system" "github.com/siderolabs/talos/internal/app/machined/pkg/system/events" "github.com/siderolabs/talos/internal/app/machined/pkg/system/health" @@ -40,6 +38,7 @@ import ( "github.com/siderolabs/talos/internal/app/machined/pkg/system/runner/restart" "github.com/siderolabs/talos/internal/pkg/containers/image" "github.com/siderolabs/talos/internal/pkg/etcd" + "github.com/siderolabs/talos/internal/pkg/meta" "github.com/siderolabs/talos/pkg/argsbuilder" "github.com/siderolabs/talos/pkg/conditions" "github.com/siderolabs/talos/pkg/filetree" @@ -377,20 +376,7 @@ func buildInitialCluster(ctx context.Context, r runtime.Runtime, name string, pe func (e *Etcd) argsForInit(ctx context.Context, r runtime.Runtime, spec *etcdresource.SpecSpec) error { var upgraded bool - if r.State().Platform().Mode() != runtime.ModeContainer { - var ( - meta *bootloader.Meta - err error - ) - - if meta, err = bootloader.NewMeta(); err != nil { - return err - } - //nolint:errcheck - defer meta.Close() - - _, upgraded = meta.LegacyADV.ReadTag(adv.Upgrade) - } + _, upgraded = r.State().Machine().Meta().ReadTag(meta.Upgrade) denyListArgs := argsbuilder.Args{ "name": spec.Name, diff --git a/internal/app/machined/revert.go b/internal/app/machined/revert.go new file mode 100644 index 000000000..5ee886357 --- /dev/null +++ b/internal/app/machined/revert.go @@ -0,0 +1,114 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package main + +import ( + "context" + "log" + "os" + + "github.com/siderolabs/go-blockdevice/blockdevice/probe" + + "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader/grub" + "github.com/siderolabs/talos/internal/pkg/meta" + "github.com/siderolabs/talos/internal/pkg/mount" + "github.com/siderolabs/talos/pkg/machinery/constants" +) + +func revertBootloader() { + if err := revertBootloadInternal(); err != nil { + log.Printf("failed to revert bootloader: %s", err) + } +} + +//nolint:gocyclo +func revertBootloadInternal() error { + metaState, err := meta.New(context.Background(), nil) + if err != nil { + if os.IsNotExist(err) { + // no META, no way to revert + return nil + } + + return err + } + + label, ok := metaState.ReadTag(meta.Upgrade) + if !ok { + return nil + } + + if label == "" { + if _, err = metaState.DeleteTag(context.Background(), meta.Upgrade); err != nil { + return err + } + + return metaState.Flush() + } + + log.Printf("reverting failed upgrade, switching to %q", label) + + // attempt to mount BOOT partition directly without using other code paths, as they rely on Runtime + dev, err := probe.GetDevWithPartitionName(constants.BootPartitionLabel) + if os.IsNotExist(err) { + // no BOOT partition??? + return nil + } + + if err != nil { + return err + } + + defer dev.Close() //nolint:errcheck + + mp, err := mount.SystemMountPointForLabel(dev.BlockDevice, constants.BootPartitionLabel) + if err != nil { + return err + } + + if mp == nil { + return nil + } + + alreadyMounted, err := mp.IsMounted() + if err != nil { + return err + } + + if !alreadyMounted { + if err = mp.Mount(); err != nil { + return err + } + + defer mp.Unmount() //nolint:errcheck + } + + conf, err := grub.Read(grub.ConfigPath) + if err != nil { + return err + } + + if conf == nil { + return nil + } + + bootEntry, err := grub.ParseBootLabel(label) + if err != nil { + return err + } + + if conf.Default != bootEntry { + conf.Default, conf.Fallback = bootEntry, conf.Default + if err = conf.Write(grub.ConfigPath); err != nil { + return err + } + } + + if _, err = metaState.DeleteTag(context.Background(), meta.Upgrade); err != nil { + return err + } + + return metaState.Flush() +} diff --git a/internal/pkg/meta/constants.go b/internal/pkg/meta/constants.go new file mode 100644 index 000000000..171896588 --- /dev/null +++ b/internal/pkg/meta/constants.go @@ -0,0 +1,16 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package meta + +const ( + // Upgrade is the upgrade tag. + Upgrade = iota + 6 + // StagedUpgradeImageRef stores image reference for staged upgrade. + StagedUpgradeImageRef + // StagedUpgradeInstallOptions stores JSON-serialized install.Options. + StagedUpgradeInstallOptions + // StateEncryptionConfig stores JSON-serialized v1alpha1.Encryption. + StateEncryptionConfig +) diff --git a/internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv/adv.go b/internal/pkg/meta/internal/adv/adv.go similarity index 64% rename from internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv/adv.go rename to internal/pkg/meta/internal/adv/adv.go index aa22a8751..39a3644b2 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv/adv.go +++ b/internal/pkg/meta/internal/adv/adv.go @@ -12,28 +12,19 @@ type ADV interface { SetTag(t uint8, val string) (ok bool) SetTagBytes(t uint8, val []byte) (ok bool) DeleteTag(t uint8) (ok bool) + ListTags() (tags []uint8) Bytes() ([]byte, error) } const ( // End is the noop tag. End = iota - // Bootonce is the bootonce tag. - Bootonce - // Menusave is the menusave tag. - Menusave + _ + _ // Reserved1 is a reserved tag. Reserved1 // Reserved2 is a reserved tag. Reserved2 // Reserved3 is a reserved tag. Reserved3 - // Upgrade is the upgrade tag. - Upgrade - // StagedUpgradeImageRef stores image reference for staged upgrade. - StagedUpgradeImageRef - // StagedUpgradeInstallOptions stores JSON-serialized install.Options. - StagedUpgradeInstallOptions - // StateEncryptionConfig stores JSON-serialized v1alpha1.Encryption. - StateEncryptionConfig ) diff --git a/internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv/syslinux/syslinux.go b/internal/pkg/meta/internal/adv/syslinux/syslinux.go similarity index 88% rename from internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv/syslinux/syslinux.go rename to internal/pkg/meta/internal/adv/syslinux/syslinux.go index 8947d8a1d..d631e8587 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv/syslinux/syslinux.go +++ b/internal/pkg/meta/internal/adv/syslinux/syslinux.go @@ -9,7 +9,7 @@ import ( "encoding/binary" "io" - "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv" + "github.com/siderolabs/talos/internal/pkg/meta/internal/adv" ) const ( @@ -30,13 +30,17 @@ type ADV []byte // NewADV returns the Auxiliary Data Vector. func NewADV(r io.ReadSeeker) (adv ADV, err error) { + b := make([]byte, 2*AdvSize) + + if r == nil { + return b, nil + } + _, err = r.Seek(-2*AdvSize, io.SeekEnd) if err != nil { return nil, err } - b := make([]byte, 2*AdvSize) - _, err = io.ReadFull(r, b) if err != nil { return nil, err @@ -90,6 +94,31 @@ func (a ADV) ReadTagBytes(t uint8) (val []byte, ok bool) { return val, ok } +// ListTags returns a list of tags in the ADV. +func (a ADV) ListTags() []uint8 { + // Header is in first 8 bytes. + i := 8 + + var tags []uint8 + + // End at tail plus two bytes required for successful next tag. + for i < AdvSize-4-2 { + tag := a[i] + size := int(a[i+1]) + + if tag == adv.End { + break + } + + tags = append(tags, tag) + + // Jump to the next tag. + i += 2 + size + } + + return tags +} + // SetTag sets a tag in the ADV. func (a ADV) SetTag(t uint8, val string) bool { return a.SetTagBytes(t, []byte(val)) diff --git a/internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv/syslinux/syslinux_test.go b/internal/pkg/meta/internal/adv/syslinux/syslinux_test.go similarity index 99% rename from internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv/syslinux/syslinux_test.go rename to internal/pkg/meta/internal/adv/syslinux/syslinux_test.go index 4e3441c60..303f8a261 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv/syslinux/syslinux_test.go +++ b/internal/pkg/meta/internal/adv/syslinux/syslinux_test.go @@ -11,8 +11,6 @@ import ( "os" "reflect" "testing" - - "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv" ) func TestNewADV(t *testing.T) { @@ -78,7 +76,7 @@ func TestADV_ReadTag(t *testing.T) { name: "bootonce", a: ADV{165, 47, 45, 90, 142, 155, 111, 208, 1, 7, 116, 101, 115, 116, 32, 109, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 191, 40, 221, 165, 47, 45, 90, 142, 155, 111, 208, 1, 7, 116, 101, 115, 116, 32, 109, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 191, 40, 221}, args: args{ - t: adv.Bootonce, + t: 1, }, wantVal: "test me", wantOk: true, @@ -97,6 +95,11 @@ func TestADV_ReadTag(t *testing.T) { if gotOk != tt.wantOk { t.Errorf("ADV.ReadTag() gotOk = %v, want %v", gotOk, tt.wantOk) } + + tags := tt.a.ListTags() + if !reflect.DeepEqual(tags, []uint8{tt.args.t}) { + t.Errorf("ADV.ListTags() got = %v, want %v", tags, []uint8{tt.args.t}) + } }) } } @@ -118,7 +121,7 @@ func TestADV_SetTag(t *testing.T) { name: "set test me", a: ADV{165, 47, 45, 90, 103, 23, 4, 163, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 191, 40, 221, 165, 47, 45, 90, 103, 23, 4, 163, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 191, 40, 221}, args: args{ - t: adv.Bootonce, + t: 1, val: "test me", }, wantADV: ADV{165, 47, 45, 90, 142, 155, 111, 208, 1, 7, 116, 101, 115, 116, 32, 109, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 191, 40, 221, 165, 47, 45, 90, 142, 155, 111, 208, 1, 7, 116, 101, 115, 116, 32, 109, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 191, 40, 221}, @@ -128,7 +131,7 @@ func TestADV_SetTag(t *testing.T) { name: "set test", a: ADV{165, 47, 45, 90, 142, 155, 111, 208, 1, 7, 116, 101, 115, 116, 32, 109, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 191, 40, 221, 165, 47, 45, 90, 142, 155, 111, 208, 1, 7, 116, 101, 115, 116, 32, 109, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 191, 40, 221}, args: args{ - t: adv.Upgrade, + t: 6, val: "add test", }, wantADV: ADV{165, 47, 45, 90, 197, 189, 210, 250, 1, 7, 116, 101, 115, 116, 32, 109, 101, 6, 8, 97, 100, 100, 32, 116, 101, 115, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 191, 40, 221, 165, 47, 45, 90, 197, 189, 210, 250, 1, 7, 116, 101, 115, 116, 32, 109, 101, 6, 8, 97, 100, 100, 32, 116, 101, 115, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 191, 40, 221}, @@ -170,7 +173,7 @@ func TestADV_DeleteTag(t *testing.T) { name: "delete test me", a: ADV{165, 47, 45, 90, 142, 155, 111, 208, 1, 7, 116, 101, 115, 116, 32, 109, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 191, 40, 221, 165, 47, 45, 90, 142, 155, 111, 208, 1, 7, 116, 101, 115, 116, 32, 109, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 191, 40, 221}, args: args{ - t: adv.Bootonce, + t: 1, }, wantADV: ADV{165, 47, 45, 90, 103, 23, 4, 163, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 191, 40, 221, 165, 47, 45, 90, 103, 23, 4, 163, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 191, 40, 221}, wantOk: true, @@ -179,7 +182,7 @@ func TestADV_DeleteTag(t *testing.T) { name: "delete test", a: ADV{165, 47, 45, 90, 185, 209, 145, 51, 1, 7, 116, 101, 115, 116, 32, 109, 101, 6, 8, 97, 100, 100, 32, 116, 101, 115, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 191, 40, 221, 165, 47, 45, 90, 185, 209, 145, 51, 1, 7, 116, 101, 115, 116, 32, 109, 101, 6, 8, 97, 100, 100, 32, 116, 101, 115, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 191, 40, 221}, args: args{ - t: adv.Upgrade, + t: 6, }, wantADV: ADV{165, 47, 45, 90, 142, 155, 111, 208, 1, 7, 116, 101, 115, 116, 32, 109, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 191, 40, 221, 165, 47, 45, 90, 142, 155, 111, 208, 1, 7, 116, 101, 115, 116, 32, 109, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 191, 40, 221}, wantOk: true, @@ -188,7 +191,7 @@ func TestADV_DeleteTag(t *testing.T) { name: "delete test again", a: ADV{165, 47, 45, 90, 142, 155, 111, 208, 1, 7, 116, 101, 115, 116, 32, 109, 101, 6, 8, 97, 100, 100, 32, 116, 101, 115, 116, 6, 8, 97, 100, 100, 32, 116, 101, 115, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 191, 40, 221, 165, 47, 45, 90, 142, 155, 111, 208, 1, 7, 116, 101, 115, 116, 32, 109, 101, 6, 8, 97, 100, 100, 32, 116, 101, 115, 116, 6, 8, 97, 100, 100, 32, 116, 101, 115, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 191, 40, 221}, args: args{ - t: adv.Upgrade, + t: 6, }, wantADV: ADV{165, 47, 45, 90, 197, 189, 210, 250, 1, 7, 116, 101, 115, 116, 32, 109, 101, 6, 8, 97, 100, 100, 32, 116, 101, 115, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 191, 40, 221, 165, 47, 45, 90, 197, 189, 210, 250, 1, 7, 116, 101, 115, 116, 32, 109, 101, 6, 8, 97, 100, 100, 32, 116, 101, 115, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 191, 40, 221}, wantOk: true, @@ -334,7 +337,7 @@ func TestADV_overwrite(t *testing.T) { } for i := 0; i < 1024; i++ { - if !a.SetTag(adv.Bootonce, "yes") { + if !a.SetTag(1, "yes") { t.Errorf("SetTag() failed") } } diff --git a/internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv/syslinux/testdata/adv.sys b/internal/pkg/meta/internal/adv/syslinux/testdata/adv.sys similarity index 100% rename from internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv/syslinux/testdata/adv.sys rename to internal/pkg/meta/internal/adv/syslinux/testdata/adv.sys diff --git a/internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv/talos/talos.go b/internal/pkg/meta/internal/adv/talos/talos.go similarity index 93% rename from internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv/talos/talos.go rename to internal/pkg/meta/internal/adv/talos/talos.go index 613c85a94..31ac60dbc 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv/talos/talos.go +++ b/internal/pkg/meta/internal/adv/talos/talos.go @@ -12,7 +12,10 @@ import ( "fmt" "io" - "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv" + "github.com/siderolabs/gen/maps" + "github.com/siderolabs/gen/slices" + + "github.com/siderolabs/talos/internal/pkg/meta/internal/adv" ) // Basic constants configuring the ADV. @@ -59,6 +62,10 @@ func NewADV(r io.Reader) (*ADV, error) { Tags: make(map[Tag]Value), } + if r == nil { + return a, nil + } + buf := make([]byte, Length) _, err := io.ReadFull(r, buf) @@ -181,6 +188,11 @@ func (a *ADV) ReadTagBytes(t uint8) (val []byte, ok bool) { return } +// ListTags to get list of tags. +func (a *ADV) ListTags() (tags []uint8) { + return slices.Map(maps.Keys(a.Tags), func(t Tag) uint8 { return uint8(t) }) +} + // SetTag to set tag value. func (a *ADV) SetTag(t uint8, val string) (ok bool) { return a.SetTagBytes(t, []byte(val)) diff --git a/internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv/talos/talos_test.go b/internal/pkg/meta/internal/adv/talos/talos_test.go similarity index 83% rename from internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv/talos/talos_test.go rename to internal/pkg/meta/internal/adv/talos/talos_test.go index fe1667290..7444845f4 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv/talos/talos_test.go +++ b/internal/pkg/meta/internal/adv/talos/talos_test.go @@ -6,13 +6,14 @@ package talos_test import ( "bytes" + "sort" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv" - "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv/talos" + "github.com/siderolabs/talos/internal/pkg/meta/internal/adv" + "github.com/siderolabs/talos/internal/pkg/meta/internal/adv/talos" ) func TestMarshalUnmarshal(t *testing.T) { @@ -82,5 +83,9 @@ func TestMarshalUnmarshal(t *testing.T) { val, ok = a.ReadTag(adv.Reserved3) assert.True(t, ok) assert.Equal(t, val3, val) + + tags := a.ListTags() + sort.Slice(tags, func(i, j int) bool { return tags[i] < tags[j] }) + assert.Equal(t, []uint8{adv.Reserved1, adv.Reserved2, adv.Reserved3}, tags) } } diff --git a/internal/pkg/meta/meta.go b/internal/pkg/meta/meta.go new file mode 100644 index 000000000..08d1a690b --- /dev/null +++ b/internal/pkg/meta/meta.go @@ -0,0 +1,341 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +// Package meta provides access to META partition: key-value partition persisted across reboots. +package meta + +import ( + "context" + "fmt" + "io" + "log" + "os" + "sync" + + "github.com/cosi-project/runtime/pkg/resource" + "github.com/cosi-project/runtime/pkg/safe" + "github.com/cosi-project/runtime/pkg/state" + "github.com/siderolabs/go-blockdevice/blockdevice/probe" + + "github.com/siderolabs/talos/internal/pkg/meta/internal/adv" + "github.com/siderolabs/talos/internal/pkg/meta/internal/adv/syslinux" + "github.com/siderolabs/talos/internal/pkg/meta/internal/adv/talos" + "github.com/siderolabs/talos/pkg/machinery/constants" + "github.com/siderolabs/talos/pkg/machinery/resources/runtime" +) + +// Meta represents the META reader/writer. +// +// Meta abstracts away all details about loading/storing the metadata providing an easy to use interface. +type Meta struct { + mu sync.Mutex + + legacy adv.ADV + talos adv.ADV + state state.State + opts Options +} + +// Options configures the META. +type Options struct { + fixedPath string +} + +// Option is a functional option. +type Option func(*Options) + +// WithFixedPath sets the fixed path to META partition. +func WithFixedPath(path string) Option { + return func(o *Options) { + o.fixedPath = path + } +} + +// New initializes empty META, trying to probe the existing META first. +func New(ctx context.Context, st state.State, opts ...Option) (*Meta, error) { + meta := &Meta{ + state: st, + } + + for _, opt := range opts { + opt(&meta.opts) + } + + var err error + + meta.legacy, err = syslinux.NewADV(nil) + if err != nil { + return nil, err + } + + meta.talos, err = talos.NewADV(nil) + if err != nil { + return nil, err + } + + err = meta.Reload(ctx) + if err != nil && !os.IsNotExist(err) { + return meta, err + } + + return meta, nil +} + +func (meta *Meta) getPath() (string, error) { + if meta.opts.fixedPath != "" { + return meta.opts.fixedPath, nil + } + + dev, err := probe.GetDevWithPartitionName(constants.MetaPartitionLabel) + if err != nil { + return "", err + } + + defer dev.Close() //nolint:errcheck + + return dev.PartPath(constants.MetaPartitionLabel) +} + +// Reload refreshes the META from the disk. +func (meta *Meta) Reload(ctx context.Context) error { + meta.mu.Lock() + defer meta.mu.Unlock() + + path, err := meta.getPath() + if err != nil { + return err + } + + f, err := os.Open(path) + if err != nil { + return err + } + + defer f.Close() //nolint:errcheck + + adv, err := talos.NewADV(f) + if adv == nil && err != nil { + // if adv is not nil, but err is nil, it might be missing ADV, ignore it + return err + } + + legacyAdv, err := syslinux.NewADV(f) + if err != nil { + return err + } + + // copy values from in-memory to on-disk version + for _, t := range meta.talos.ListTags() { + val, _ := meta.talos.ReadTagBytes(t) + adv.SetTagBytes(t, val) + } + + log.Printf("META: loaded %d keys", len(adv.ListTags())) + + meta.talos = adv + meta.legacy = legacyAdv + + return meta.syncState(ctx) +} + +// syncState sync resources with adv contents. +func (meta *Meta) syncState(ctx context.Context) error { + if meta.state == nil { + return nil + } + + existingTags := make(map[resource.ID]struct{}) + + for _, t := range meta.talos.ListTags() { + existingTags[tagToID(t)] = struct{}{} + val, _ := meta.talos.ReadTag(t) + + if err := updateTagResource(ctx, meta.state, t, val); err != nil { + return err + } + } + + items, err := meta.state.List(ctx, runtime.NewMetaKey(runtime.NamespaceName, "").Metadata()) + if err != nil { + return err + } + + for _, item := range items.Items { + if _, exists := existingTags[item.Metadata().ID()]; exists { + continue + } + + if err = meta.state.Destroy(ctx, item.Metadata()); err != nil { + return err + } + } + + return nil +} + +// Flush writes the META to the disk. +func (meta *Meta) Flush() error { + meta.mu.Lock() + defer meta.mu.Unlock() + + path, err := meta.getPath() + if err != nil { + return err + } + + f, err := os.OpenFile(path, os.O_RDWR, 0) + if err != nil { + return err + } + + defer f.Close() //nolint:errcheck + + serialized, err := meta.talos.Bytes() + if err != nil { + return err + } + + n, err := f.WriteAt(serialized, 0) + if err != nil { + return err + } + + if n != len(serialized) { + return fmt.Errorf("expected to write %d bytes, wrote %d", len(serialized), n) + } + + serialized, err = meta.legacy.Bytes() + if err != nil { + return err + } + + offset, err := f.Seek(-int64(len(serialized)), io.SeekEnd) + if err != nil { + return err + } + + n, err = f.WriteAt(serialized, offset) + if err != nil { + return err + } + + if n != len(serialized) { + return fmt.Errorf("expected to write %d bytes, wrote %d", len(serialized), n) + } + + log.Printf("META: saved %d keys", len(meta.talos.ListTags())) + + return f.Sync() +} + +// ReadTag reads a tag from the META. +func (meta *Meta) ReadTag(t uint8) (val string, ok bool) { + meta.mu.Lock() + defer meta.mu.Unlock() + + val, ok = meta.talos.ReadTag(t) + if !ok { + val, ok = meta.legacy.ReadTag(t) + } + + return val, ok +} + +// ReadTagBytes reads a tag from the META. +func (meta *Meta) ReadTagBytes(t uint8) (val []byte, ok bool) { + meta.mu.Lock() + defer meta.mu.Unlock() + + val, ok = meta.talos.ReadTagBytes(t) + if !ok { + val, ok = meta.legacy.ReadTagBytes(t) + } + + return val, ok +} + +// SetTag writes a tag to the META. +func (meta *Meta) SetTag(ctx context.Context, t uint8, val string) (bool, error) { + meta.mu.Lock() + defer meta.mu.Unlock() + + ok := meta.talos.SetTag(t, val) + + if ok { + err := updateTagResource(ctx, meta.state, t, val) + if err != nil { + return false, err + } + } + + return ok, nil +} + +// SetTagBytes writes a tag to the META. +func (meta *Meta) SetTagBytes(ctx context.Context, t uint8, val []byte) (bool, error) { + meta.mu.Lock() + defer meta.mu.Unlock() + + ok := meta.talos.SetTagBytes(t, val) + + if ok { + err := updateTagResource(ctx, meta.state, t, string(val)) + if err != nil { + return false, err + } + } + + return ok, nil +} + +// DeleteTag deletes a tag from the META. +func (meta *Meta) DeleteTag(ctx context.Context, t uint8) (bool, error) { + meta.mu.Lock() + defer meta.mu.Unlock() + + ok := meta.talos.DeleteTag(t) + if !ok { + ok = meta.legacy.DeleteTag(t) + } + + if meta.state == nil { + return ok, nil + } + + err := meta.state.Destroy(ctx, runtime.NewMetaKey(runtime.NamespaceName, tagToID(t)).Metadata()) //nolint:errcheck + if state.IsNotFoundError(err) { + err = nil + } + + return ok, err +} + +func tagToID(t uint8) resource.ID { + return fmt.Sprintf("0x%02x", t) +} + +func updateTagResource(ctx context.Context, st state.State, t uint8, val string) error { + if st == nil { + return nil + } + + _, err := safe.StateUpdateWithConflicts(ctx, st, runtime.NewMetaKey(runtime.NamespaceName, tagToID(t)).Metadata(), func(r *runtime.MetaKey) error { + r.TypedSpec().Value = val + + return nil + }) + + if err == nil { + return nil + } + + if state.IsNotFoundError(err) { + r := runtime.NewMetaKey(runtime.NamespaceName, tagToID(t)) + r.TypedSpec().Value = val + + return st.Create(ctx, r) + } + + return err +} diff --git a/internal/pkg/meta/meta_test.go b/internal/pkg/meta/meta_test.go new file mode 100644 index 000000000..d258c46bd --- /dev/null +++ b/internal/pkg/meta/meta_test.go @@ -0,0 +1,98 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +// Package meta provides access to META partition: key-value partition persisted across reboots. +package meta_test + +import ( + "context" + "os" + "path/filepath" + "testing" + + "github.com/cosi-project/runtime/pkg/safe" + "github.com/cosi-project/runtime/pkg/state" + "github.com/cosi-project/runtime/pkg/state/impl/inmem" + "github.com/cosi-project/runtime/pkg/state/impl/namespaced" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/siderolabs/talos/internal/pkg/meta" + "github.com/siderolabs/talos/pkg/machinery/resources/runtime" +) + +func setupTest(t *testing.T) (*meta.Meta, string, state.State) { + t.Helper() + + tmpDir := t.TempDir() + + path := filepath.Join(tmpDir, "meta") + + f, err := os.Create(path) + require.NoError(t, err) + + require.NoError(t, f.Truncate(1024*1024)) + + require.NoError(t, f.Close()) + + st := state.WrapCore(namespaced.NewState(inmem.Build)) + + m, err := meta.New(context.Background(), st, meta.WithFixedPath(path)) + require.NoError(t, err) + + return m, path, st +} + +func TestFlow(t *testing.T) { + t.Parallel() + + m, path, st := setupTest(t) + + ctx := context.Background() + + ok, err := m.SetTag(ctx, meta.Upgrade, "1.2.3") + require.NoError(t, err) + assert.True(t, ok) + + val, ok := m.ReadTag(meta.Upgrade) + assert.True(t, ok) + assert.Equal(t, "1.2.3", val) + + _, ok = m.ReadTag(meta.StagedUpgradeImageRef) + assert.False(t, ok) + + ok, err = m.DeleteTag(ctx, meta.Upgrade) + require.NoError(t, err) + assert.True(t, ok) + + ok, err = m.SetTag(ctx, meta.StagedUpgradeInstallOptions, "install-fast") + require.NoError(t, err) + assert.True(t, ok) + + assert.NoError(t, m.Flush()) + + assert.NoError(t, m.Reload(ctx)) + + val, ok = m.ReadTag(meta.StagedUpgradeInstallOptions) + assert.True(t, ok) + assert.Equal(t, "install-fast", val) + + m2, err := meta.New(ctx, st, meta.WithFixedPath(path)) + require.NoError(t, err) + + _, ok = m2.ReadTag(meta.Upgrade) + assert.False(t, ok) + + val, ok = m2.ReadTag(meta.StagedUpgradeInstallOptions) + assert.True(t, ok) + assert.Equal(t, "install-fast", val) + + list, err := safe.StateList[*runtime.MetaKey](ctx, st, runtime.NewMetaKey(runtime.NamespaceName, "").Metadata()) + require.NoError(t, err) + + for iter := safe.IteratorFromList(list); iter.Next(); { + assert.Equal(t, "0x08", iter.Value().Metadata().ID()) + assert.Equal(t, "install-fast", iter.Value().TypedSpec().Value) + } +} diff --git a/pkg/machinery/api/resource/definitions/runtime/runtime.pb.go b/pkg/machinery/api/resource/definitions/runtime/runtime.pb.go index 90df98250..ce3857fb9 100644 --- a/pkg/machinery/api/resource/definitions/runtime/runtime.pb.go +++ b/pkg/machinery/api/resource/definitions/runtime/runtime.pb.go @@ -311,6 +311,54 @@ func (x *MachineStatusStatus) GetUnmetConditions() []*UnmetCondition { return nil } +// MetaKeySpec describes status of the defined sysctls. +type MetaKeySpec struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *MetaKeySpec) Reset() { + *x = MetaKeySpec{} + if protoimpl.UnsafeEnabled { + mi := &file_resource_definitions_runtime_runtime_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MetaKeySpec) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MetaKeySpec) ProtoMessage() {} + +func (x *MetaKeySpec) ProtoReflect() protoreflect.Message { + mi := &file_resource_definitions_runtime_runtime_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MetaKeySpec.ProtoReflect.Descriptor instead. +func (*MetaKeySpec) Descriptor() ([]byte, []int) { + return file_resource_definitions_runtime_runtime_proto_rawDescGZIP(), []int{5} +} + +func (x *MetaKeySpec) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + // MountStatusSpec describes status of the defined sysctls. type MountStatusSpec struct { state protoimpl.MessageState @@ -326,7 +374,7 @@ type MountStatusSpec struct { func (x *MountStatusSpec) Reset() { *x = MountStatusSpec{} if protoimpl.UnsafeEnabled { - mi := &file_resource_definitions_runtime_runtime_proto_msgTypes[5] + mi := &file_resource_definitions_runtime_runtime_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -339,7 +387,7 @@ func (x *MountStatusSpec) String() string { func (*MountStatusSpec) ProtoMessage() {} func (x *MountStatusSpec) ProtoReflect() protoreflect.Message { - mi := &file_resource_definitions_runtime_runtime_proto_msgTypes[5] + mi := &file_resource_definitions_runtime_runtime_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -352,7 +400,7 @@ func (x *MountStatusSpec) ProtoReflect() protoreflect.Message { // Deprecated: Use MountStatusSpec.ProtoReflect.Descriptor instead. func (*MountStatusSpec) Descriptor() ([]byte, []int) { - return file_resource_definitions_runtime_runtime_proto_rawDescGZIP(), []int{5} + return file_resource_definitions_runtime_runtime_proto_rawDescGZIP(), []int{6} } func (x *MountStatusSpec) GetSource() string { @@ -402,7 +450,7 @@ type PlatformMetadataSpec struct { func (x *PlatformMetadataSpec) Reset() { *x = PlatformMetadataSpec{} if protoimpl.UnsafeEnabled { - mi := &file_resource_definitions_runtime_runtime_proto_msgTypes[6] + mi := &file_resource_definitions_runtime_runtime_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -415,7 +463,7 @@ func (x *PlatformMetadataSpec) String() string { func (*PlatformMetadataSpec) ProtoMessage() {} func (x *PlatformMetadataSpec) ProtoReflect() protoreflect.Message { - mi := &file_resource_definitions_runtime_runtime_proto_msgTypes[6] + mi := &file_resource_definitions_runtime_runtime_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -428,7 +476,7 @@ func (x *PlatformMetadataSpec) ProtoReflect() protoreflect.Message { // Deprecated: Use PlatformMetadataSpec.ProtoReflect.Descriptor instead. func (*PlatformMetadataSpec) Descriptor() ([]byte, []int) { - return file_resource_definitions_runtime_runtime_proto_rawDescGZIP(), []int{6} + return file_resource_definitions_runtime_runtime_proto_rawDescGZIP(), []int{7} } func (x *PlatformMetadataSpec) GetPlatform() string { @@ -500,7 +548,7 @@ type UnmetCondition struct { func (x *UnmetCondition) Reset() { *x = UnmetCondition{} if protoimpl.UnsafeEnabled { - mi := &file_resource_definitions_runtime_runtime_proto_msgTypes[7] + mi := &file_resource_definitions_runtime_runtime_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -513,7 +561,7 @@ func (x *UnmetCondition) String() string { func (*UnmetCondition) ProtoMessage() {} func (x *UnmetCondition) ProtoReflect() protoreflect.Message { - mi := &file_resource_definitions_runtime_runtime_proto_msgTypes[7] + mi := &file_resource_definitions_runtime_runtime_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -526,7 +574,7 @@ func (x *UnmetCondition) ProtoReflect() protoreflect.Message { // Deprecated: Use UnmetCondition.ProtoReflect.Descriptor instead. func (*UnmetCondition) Descriptor() ([]byte, []int) { - return file_resource_definitions_runtime_runtime_proto_rawDescGZIP(), []int{7} + return file_resource_definitions_runtime_runtime_proto_rawDescGZIP(), []int{8} } func (x *UnmetCondition) GetName() string { @@ -590,40 +638,42 @@ var file_resource_definitions_runtime_runtime_proto_rawDesc = []byte{ 0x63, 0x65, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x55, 0x6e, 0x6d, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x75, 0x6e, 0x6d, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x64, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x84, 0x01, 0x0a, 0x0f, 0x4d, 0x6f, 0x75, 0x6e, 0x74, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x53, 0x70, 0x65, 0x63, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x66, 0x69, - 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, - 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xf5, 0x01, - 0x0a, 0x14, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x53, 0x70, 0x65, 0x63, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, - 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, - 0x72, 0x6d, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, - 0x0a, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x7a, 0x6f, 0x6e, 0x65, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x7a, 0x6f, 0x6e, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6e, - 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0c, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, - 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, - 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, - 0x64, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x70, 0x6f, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x04, 0x73, 0x70, 0x6f, 0x74, 0x22, 0x3c, 0x0a, 0x0e, 0x55, 0x6e, 0x6d, 0x65, 0x74, 0x43, 0x6f, - 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, - 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, - 0x73, 0x6f, 0x6e, 0x42, 0x4c, 0x5a, 0x4a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x73, 0x69, 0x64, 0x65, 0x72, 0x6f, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x74, 0x61, 0x6c, - 0x6f, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x72, 0x79, - 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x64, 0x65, - 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, - 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x23, 0x0a, 0x0b, 0x4d, 0x65, 0x74, 0x61, 0x4b, 0x65, + 0x79, 0x53, 0x70, 0x65, 0x63, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x84, 0x01, 0x0a, 0x0f, + 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x53, 0x70, 0x65, 0x63, 0x12, + 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, + 0x27, 0x0a, 0x0f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, + 0x73, 0x74, 0x65, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x22, 0xf5, 0x01, 0x0a, 0x14, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x53, 0x70, 0x65, 0x63, 0x12, 0x1a, 0x0a, 0x08, 0x70, + 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, + 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x7a, + 0x6f, 0x6e, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x7a, 0x6f, 0x6e, 0x65, 0x12, + 0x23, 0x0a, 0x0d, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, + 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, + 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x70, 0x6f, 0x74, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x73, 0x70, 0x6f, 0x74, 0x22, 0x3c, 0x0a, 0x0e, 0x55, 0x6e, + 0x6d, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x42, 0x4c, 0x5a, 0x4a, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x69, 0x64, 0x65, 0x72, 0x6f, 0x6c, 0x61, 0x62, + 0x73, 0x2f, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x6d, 0x61, 0x63, 0x68, + 0x69, 0x6e, 0x65, 0x72, 0x79, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x2f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x72, + 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -638,22 +688,23 @@ func file_resource_definitions_runtime_runtime_proto_rawDescGZIP() []byte { return file_resource_definitions_runtime_runtime_proto_rawDescData } -var file_resource_definitions_runtime_runtime_proto_msgTypes = make([]protoimpl.MessageInfo, 8) +var file_resource_definitions_runtime_runtime_proto_msgTypes = make([]protoimpl.MessageInfo, 9) var file_resource_definitions_runtime_runtime_proto_goTypes = []interface{}{ (*KernelModuleSpecSpec)(nil), // 0: talos.resource.definitions.runtime.KernelModuleSpecSpec (*KernelParamSpecSpec)(nil), // 1: talos.resource.definitions.runtime.KernelParamSpecSpec (*KernelParamStatusSpec)(nil), // 2: talos.resource.definitions.runtime.KernelParamStatusSpec (*MachineStatusSpec)(nil), // 3: talos.resource.definitions.runtime.MachineStatusSpec (*MachineStatusStatus)(nil), // 4: talos.resource.definitions.runtime.MachineStatusStatus - (*MountStatusSpec)(nil), // 5: talos.resource.definitions.runtime.MountStatusSpec - (*PlatformMetadataSpec)(nil), // 6: talos.resource.definitions.runtime.PlatformMetadataSpec - (*UnmetCondition)(nil), // 7: talos.resource.definitions.runtime.UnmetCondition - (enums.RuntimeMachineStage)(0), // 8: talos.resource.definitions.enums.RuntimeMachineStage + (*MetaKeySpec)(nil), // 5: talos.resource.definitions.runtime.MetaKeySpec + (*MountStatusSpec)(nil), // 6: talos.resource.definitions.runtime.MountStatusSpec + (*PlatformMetadataSpec)(nil), // 7: talos.resource.definitions.runtime.PlatformMetadataSpec + (*UnmetCondition)(nil), // 8: talos.resource.definitions.runtime.UnmetCondition + (enums.RuntimeMachineStage)(0), // 9: talos.resource.definitions.enums.RuntimeMachineStage } var file_resource_definitions_runtime_runtime_proto_depIdxs = []int32{ - 8, // 0: talos.resource.definitions.runtime.MachineStatusSpec.stage:type_name -> talos.resource.definitions.enums.RuntimeMachineStage + 9, // 0: talos.resource.definitions.runtime.MachineStatusSpec.stage:type_name -> talos.resource.definitions.enums.RuntimeMachineStage 4, // 1: talos.resource.definitions.runtime.MachineStatusSpec.status:type_name -> talos.resource.definitions.runtime.MachineStatusStatus - 7, // 2: talos.resource.definitions.runtime.MachineStatusStatus.unmet_conditions:type_name -> talos.resource.definitions.runtime.UnmetCondition + 8, // 2: talos.resource.definitions.runtime.MachineStatusStatus.unmet_conditions:type_name -> talos.resource.definitions.runtime.UnmetCondition 3, // [3:3] is the sub-list for method output_type 3, // [3:3] is the sub-list for method input_type 3, // [3:3] is the sub-list for extension type_name @@ -728,7 +779,7 @@ func file_resource_definitions_runtime_runtime_proto_init() { } } file_resource_definitions_runtime_runtime_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MountStatusSpec); i { + switch v := v.(*MetaKeySpec); i { case 0: return &v.state case 1: @@ -740,7 +791,7 @@ func file_resource_definitions_runtime_runtime_proto_init() { } } file_resource_definitions_runtime_runtime_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PlatformMetadataSpec); i { + switch v := v.(*MountStatusSpec); i { case 0: return &v.state case 1: @@ -752,6 +803,18 @@ func file_resource_definitions_runtime_runtime_proto_init() { } } file_resource_definitions_runtime_runtime_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PlatformMetadataSpec); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_resource_definitions_runtime_runtime_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UnmetCondition); i { case 0: return &v.state @@ -770,7 +833,7 @@ func file_resource_definitions_runtime_runtime_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_resource_definitions_runtime_runtime_proto_rawDesc, NumEnums: 0, - NumMessages: 8, + NumMessages: 9, NumExtensions: 0, NumServices: 0, }, diff --git a/pkg/machinery/api/resource/definitions/runtime/runtime_vtproto.pb.go b/pkg/machinery/api/resource/definitions/runtime/runtime_vtproto.pb.go index 23b0f3ea6..6eeec2b36 100644 --- a/pkg/machinery/api/resource/definitions/runtime/runtime_vtproto.pb.go +++ b/pkg/machinery/api/resource/definitions/runtime/runtime_vtproto.pb.go @@ -280,6 +280,46 @@ func (m *MachineStatusStatus) MarshalToSizedBufferVT(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *MetaKeySpec) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MetaKeySpec) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *MetaKeySpec) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.Value) > 0 { + i -= len(m.Value) + copy(dAtA[i:], m.Value) + i = encodeVarint(dAtA, i, uint64(len(m.Value))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *MountStatusSpec) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil @@ -587,6 +627,20 @@ func (m *MachineStatusStatus) SizeVT() (n int) { return n } +func (m *MetaKeySpec) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Value) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + n += len(m.unknownFields) + return n +} + func (m *MountStatusSpec) SizeVT() (n int) { if m == nil { return 0 @@ -1244,6 +1298,89 @@ func (m *MachineStatusStatus) UnmarshalVT(dAtA []byte) error { } return nil } +func (m *MetaKeySpec) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MetaKeySpec: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MetaKeySpec: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Value = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *MountStatusSpec) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/pkg/machinery/resources/runtime/deep_copy.generated.go b/pkg/machinery/resources/runtime/deep_copy.generated.go index af44917fa..160864156 100644 --- a/pkg/machinery/resources/runtime/deep_copy.generated.go +++ b/pkg/machinery/resources/runtime/deep_copy.generated.go @@ -2,7 +2,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -// Code generated by "deep-copy -type KernelModuleSpecSpec -type KernelParamSpecSpec -type KernelParamStatusSpec -type MachineStatusSpec -type MountStatusSpec -type PlatformMetadataSpec -header-file ../../../../hack/boilerplate.txt -o deep_copy.generated.go ."; DO NOT EDIT. +// Code generated by "deep-copy -type KernelModuleSpecSpec -type KernelParamSpecSpec -type KernelParamStatusSpec -type MachineStatusSpec -type MetaKeySpec -type MountStatusSpec -type PlatformMetadataSpec -header-file ../../../../hack/boilerplate.txt -o deep_copy.generated.go ."; DO NOT EDIT. package runtime @@ -38,6 +38,12 @@ func (o MachineStatusSpec) DeepCopy() MachineStatusSpec { return cp } +// DeepCopy generates a deep copy of MetaKeySpec. +func (o MetaKeySpec) DeepCopy() MetaKeySpec { + var cp MetaKeySpec = o + return cp +} + // DeepCopy generates a deep copy of MountStatusSpec. func (o MountStatusSpec) DeepCopy() MountStatusSpec { var cp MountStatusSpec = o diff --git a/pkg/machinery/resources/runtime/meta_key.go b/pkg/machinery/resources/runtime/meta_key.go new file mode 100644 index 000000000..7624b1be9 --- /dev/null +++ b/pkg/machinery/resources/runtime/meta_key.go @@ -0,0 +1,62 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package runtime + +import ( + "github.com/cosi-project/runtime/pkg/resource" + "github.com/cosi-project/runtime/pkg/resource/meta" + "github.com/cosi-project/runtime/pkg/resource/protobuf" + "github.com/cosi-project/runtime/pkg/resource/typed" + + "github.com/siderolabs/talos/pkg/machinery/proto" +) + +// MetaKeyType is type of MetaKey resource. +const MetaKeyType = resource.Type("MetaKeys.runtime.talos.dev") + +// MetaKey resource holds value of a key in META partition. +type MetaKey = typed.Resource[MetaKeySpec, MetaKeyExtension] + +// MetaKeySpec describes status of the defined sysctls. +// +//gotagsrewrite:gen +type MetaKeySpec struct { + Value string `yaml:"value" protobuf:"1"` +} + +// NewMetaKey initializes a MetaKey resource. +func NewMetaKey(namespace resource.Namespace, id resource.ID) *MetaKey { + return typed.NewResource[MetaKeySpec, MetaKeyExtension]( + resource.NewMetadata(namespace, MetaKeyType, id, resource.VersionUndefined), + MetaKeySpec{}, + ) +} + +// MetaKeyExtension is auxiliary resource data for MetaKey. +type MetaKeyExtension struct{} + +// ResourceDefinition implements meta.ResourceDefinitionProvider interface. +func (MetaKeyExtension) ResourceDefinition() meta.ResourceDefinitionSpec { + return meta.ResourceDefinitionSpec{ + Type: MetaKeyType, + Aliases: []resource.Type{"meta"}, + DefaultNamespace: NamespaceName, + PrintColumns: []meta.PrintColumn{ + { + Name: "Value", + JSONPath: `{.value}`, + }, + }, + } +} + +func init() { + proto.RegisterDefaultTypes() + + err := protobuf.RegisterDynamic[MetaKeySpec](MetaKeyType, &MetaKey{}) + if err != nil { + panic(err) + } +} diff --git a/pkg/machinery/resources/runtime/runtime.go b/pkg/machinery/resources/runtime/runtime.go index ea23f36f6..721478147 100644 --- a/pkg/machinery/resources/runtime/runtime.go +++ b/pkg/machinery/resources/runtime/runtime.go @@ -5,4 +5,4 @@ package runtime //nolint:lll -//go:generate deep-copy -type KernelModuleSpecSpec -type KernelParamSpecSpec -type KernelParamStatusSpec -type MachineStatusSpec -type MountStatusSpec -type PlatformMetadataSpec -header-file ../../../../hack/boilerplate.txt -o deep_copy.generated.go . +//go:generate deep-copy -type KernelModuleSpecSpec -type KernelParamSpecSpec -type KernelParamStatusSpec -type MachineStatusSpec -type MetaKeySpec -type MountStatusSpec -type PlatformMetadataSpec -header-file ../../../../hack/boilerplate.txt -o deep_copy.generated.go . diff --git a/pkg/machinery/resources/runtime/runtime_test.go b/pkg/machinery/resources/runtime/runtime_test.go index ebdaa5fb1..b4017c732 100644 --- a/pkg/machinery/resources/runtime/runtime_test.go +++ b/pkg/machinery/resources/runtime/runtime_test.go @@ -30,6 +30,7 @@ func TestRegisterResource(t *testing.T) { &runtime.KernelParamSpec{}, &runtime.KernelParamStatus{}, &runtime.MachineStatus{}, + &runtime.MetaKey{}, &runtime.MountStatus{}, &runtime.PlatformMetadata{}, } { diff --git a/website/content/v1.4/reference/api.md b/website/content/v1.4/reference/api.md index f47d90cb0..7eee74ef0 100644 --- a/website/content/v1.4/reference/api.md +++ b/website/content/v1.4/reference/api.md @@ -176,6 +176,7 @@ description: Talos gRPC API reference. - [KernelParamStatusSpec](#talos.resource.definitions.runtime.KernelParamStatusSpec) - [MachineStatusSpec](#talos.resource.definitions.runtime.MachineStatusSpec) - [MachineStatusStatus](#talos.resource.definitions.runtime.MachineStatusStatus) + - [MetaKeySpec](#talos.resource.definitions.runtime.MetaKeySpec) - [MountStatusSpec](#talos.resource.definitions.runtime.MountStatusSpec) - [PlatformMetadataSpec](#talos.resource.definitions.runtime.PlatformMetadataSpec) - [UnmetCondition](#talos.resource.definitions.runtime.UnmetCondition) @@ -3222,6 +3223,21 @@ MachineStatusStatus describes machine current status at the stage. + + +### MetaKeySpec +MetaKeySpec describes status of the defined sysctls. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| value | [string](#string) | | | + + + + + + ### MountStatusSpec