-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
upgrade(installer): Persist task state when the installer restarts
- Loading branch information
1 parent
c99883d
commit d5e0c05
Showing
7 changed files
with
168 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
// Unless explicitly stated otherwise all files in this repository are licensed | ||
// under the Apache License Version 2.0. | ||
// This product includes software developed at Datadog (https://www.datadoghq.com/). | ||
// Copyright 2016-present Datadog, Inc. | ||
|
||
package db | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
|
||
installerErrors "github.com/DataDog/datadog-agent/pkg/fleet/installer/errors" | ||
pbgo "github.com/DataDog/datadog-agent/pkg/proto/pbgo/core" | ||
"go.etcd.io/bbolt" | ||
) | ||
|
||
var ( | ||
bucketTasks = []byte("tasks") | ||
lastTaskKey = []byte("last_task") | ||
) | ||
|
||
// RequestState represents the state of a task. | ||
type RequestState struct { | ||
Package string `json:"package"` | ||
ID string `json:"id"` | ||
State pbgo.TaskState `json:"state"` | ||
Err error `json:"error,omitempty"` | ||
ErrorCode installerErrors.InstallerErrorCode `json:"error_code,omitempty"` | ||
} | ||
|
||
// TasksDB is a database that stores information about tasks. | ||
// It is opened by the installer daemon. | ||
type TasksDB struct { | ||
db *bbolt.DB | ||
} | ||
|
||
// New creates a new TasksDB | ||
func NewTasksDB(dbPath string, opts ...Option) (*TasksDB, error) { | ||
o := options{} | ||
for _, opt := range opts { | ||
opt(&o) | ||
} | ||
db, err := bbolt.Open(dbPath, 0644, &bbolt.Options{ | ||
Timeout: o.timeout, | ||
FreelistType: bbolt.FreelistArrayType, | ||
}) | ||
if err != nil { | ||
return nil, fmt.Errorf("could not open database: %w", err) | ||
} | ||
err = db.Update(func(tx *bbolt.Tx) error { | ||
_, err := tx.CreateBucketIfNotExists(bucketTasks) | ||
return err | ||
}) | ||
if err != nil { | ||
return nil, fmt.Errorf("could not create tasks bucket: %w", err) | ||
} | ||
return &TasksDB{ | ||
db: db, | ||
}, nil | ||
} | ||
|
||
// Close closes the database | ||
func (p *TasksDB) Close() error { | ||
return p.db.Close() | ||
} | ||
|
||
// SetLastTask sets the last task | ||
func (p *TasksDB) SetLastTask(task *RequestState) error { | ||
err := p.db.Update(func(tx *bbolt.Tx) error { | ||
b := tx.Bucket(bucketTasks) | ||
if b == nil { | ||
return fmt.Errorf("bucket not found") | ||
} | ||
rawTask, err := json.Marshal(&task) | ||
if err != nil { | ||
return fmt.Errorf("could not marshal task: %w", err) | ||
} | ||
return b.Put(lastTaskKey, rawTask) | ||
}) | ||
if err != nil { | ||
return fmt.Errorf("could not set task: %w", err) | ||
} | ||
return nil | ||
} | ||
|
||
// GetLastTask retrieves the last task | ||
func (p *TasksDB) GetLastTask() (*RequestState, error) { | ||
var task *RequestState | ||
err := p.db.View(func(tx *bbolt.Tx) error { | ||
b := tx.Bucket(bucketPackages) | ||
if b == nil { | ||
return fmt.Errorf("bucket not found") | ||
} | ||
v := b.Get(lastTaskKey) | ||
if len(v) == 0 { | ||
// No task found, no error | ||
return nil | ||
} | ||
err := json.Unmarshal(v, task) | ||
if err != nil { | ||
return fmt.Errorf("could not unmarshal task: %w", err) | ||
} | ||
return nil | ||
}) | ||
if err != nil { | ||
return nil, fmt.Errorf("could not get task: %w", err) | ||
} | ||
return task, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// Unless explicitly stated otherwise all files in this repository are licensed | ||
// under the Apache License Version 2.0. | ||
// This product includes software developed at Datadog (https://www.datadoghq.com/). | ||
// Copyright 2016-present Datadog, Inc. | ||
|
||
package db | ||
|
||
import "time" | ||
|
||
type options struct { | ||
timeout time.Duration | ||
} | ||
|
||
// Option is a function that sets an option on a PackagesDB | ||
type Option func(*options) | ||
|
||
// WithTimeout sets the timeout for opening the database | ||
func WithTimeout(timeout time.Duration) Option { | ||
return func(o *options) { | ||
o.timeout = timeout | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters