Skip to content

Commit 7b44e0c

Browse files
committed
feat(storage): implement soft-delete functionality for deployments and twins
- Added soft-delete tests for deployments, twins, and workloads in storage_test.go. - Implemented methods to check if deployments and twins are deleted. - Enhanced the Delete method to support soft-deletion and verify the state of deleted items.
1 parent 2c3b580 commit 7b44e0c

15 files changed

Lines changed: 1647 additions & 135 deletions

File tree

pkg/debugcmd/deps.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@ import (
1111
"github.com/threefoldtech/zosbase/pkg/gridtypes/zos"
1212
)
1313

14-
// Provision is the subset of the provision zbus interface used by debug commands.
15-
type Provision interface {
16-
ListTwins(ctx context.Context) ([]uint32, error)
17-
List(ctx context.Context, twin uint32) ([]gridtypes.Deployment, error)
18-
Get(ctx context.Context, twin uint32, contract uint64) (gridtypes.Deployment, error)
19-
Changes(ctx context.Context, twin uint32, contract uint64) ([]gridtypes.Workload, error)
14+
// Storage is the subset of the provision interface used by debug commands.
15+
type Storage interface {
16+
GetDeployment(ctx context.Context, twin uint32, contractID uint64) (gridtypes.Deployment, error)
17+
GetDeployments(ctx context.Context, twin uint32) ([]gridtypes.Deployment, error)
18+
GetTwins(ctx context.Context) ([]uint32, error)
19+
Changes(ctx context.Context, twin uint32, contractID uint64) ([]gridtypes.Workload, error)
20+
GetWorkload(ctx context.Context, twin uint32, contractID uint64, name gridtypes.Name) (gridtypes.Workload, bool, error)
2021
}
2122

2223
// VM is the subset of the vmd zbus interface used by debug commands.
@@ -33,9 +34,9 @@ type Network interface {
3334
}
3435

3536
type Deps struct {
36-
Provision Provision
37-
VM VM
38-
Network Network
37+
VM VM
38+
Network Network
39+
Storage Storage
3940
}
4041

4142
// ParseDeploymentID parses a deployment identifier in the format "twin-id:contract-id"

pkg/debugcmd/get.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ func Get(ctx context.Context, deps Deps, req GetRequest) (GetResponse, error) {
2929
return GetResponse{}, err
3030
}
3131

32-
// TODO: only return active deployment. should return all
33-
deployment, err := deps.Provision.Get(ctx, twinID, contractID)
32+
deployment, err := deps.Storage.GetDeployment(ctx, twinID, contractID)
3433
if err != nil {
3534
return GetResponse{}, err
3635
}

pkg/debugcmd/health.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ func Health(ctx context.Context, deps Deps, req HealthRequest) (HealthResponse,
6969
}
7070

7171
if req.Deployment != "" {
72-
deployment, err := deps.Provision.Get(ctx, twinID, contractID)
72+
deployment, err := deps.Storage.GetDeployment(ctx, twinID, contractID)
7373
if err != nil {
7474
return HealthResponse{}, fmt.Errorf("failed to get deployment: %w", err)
7575
}

pkg/debugcmd/history.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@ func History(ctx context.Context, deps Deps, req HistoryRequest) (HistoryRespons
3939
return HistoryResponse{}, err
4040
}
4141

42-
// TODO: only return history for active deployment.
43-
history, err := deps.Provision.Changes(ctx, twinID, contractID)
42+
history, err := deps.Storage.Changes(ctx, twinID, contractID)
4443
if err != nil {
4544
return HistoryResponse{}, err
4645
}

pkg/debugcmd/info.go

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,20 +41,11 @@ func Info(ctx context.Context, deps Deps, req InfoRequest) (InfoResponse, error)
4141
return InfoResponse{}, err
4242
}
4343

44-
deployment, err := deps.Provision.Get(ctx, twinID, contractID)
44+
workload, found, err := deps.Storage.GetWorkload(ctx, twinID, contractID, gridtypes.Name(req.Workload))
4545
if err != nil {
46-
return InfoResponse{}, fmt.Errorf("failed to get deployment: %w", err)
46+
return InfoResponse{}, fmt.Errorf("failed to get workload: %w", err)
4747
}
48-
49-
var workload *gridtypes.Workload
50-
for i := range deployment.Workloads {
51-
if string(deployment.Workloads[i].Name) == req.Workload {
52-
workload = &deployment.Workloads[i]
53-
break
54-
}
55-
}
56-
57-
if workload == nil {
48+
if !found {
5849
return InfoResponse{}, fmt.Errorf("workload '%s' not found in deployment", req.Workload)
5950
}
6051

@@ -70,7 +61,7 @@ func Info(ctx context.Context, deps Deps, req InfoRequest) (InfoResponse, error)
7061
case zos.ZMachineType, zos.ZMachineLightType:
7162
return handleZMachineInfo(ctx, deps, workloadID.String(), req.Verbose, resp)
7263
case zos.NetworkType, zos.NetworkLightType:
73-
return handleNetworkInfo(ctx, deps, twinID, workload, resp)
64+
return handleNetworkInfo(ctx, deps, twinID, &workload, resp)
7465
default:
7566
return InfoResponse{}, fmt.Errorf("workload type '%s' not supported for info command", workload.Type)
7667
}

pkg/debugcmd/list.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,16 @@ func ParseListRequest(payload []byte) (ListRequest, error) {
4040
func List(ctx context.Context, deps Deps, req ListRequest) (ListResponse, error) {
4141
twins := []uint32{req.TwinID}
4242
if req.TwinID == 0 {
43-
allTwins, err := deps.Provision.ListTwins(ctx)
43+
var err error
44+
twins, err = deps.Storage.GetTwins(ctx)
4445
if err != nil {
4546
return ListResponse{}, err
4647
}
47-
48-
twins = allTwins
4948
}
5049

5150
deployments := make([]ListDeployment, 0)
5251
for _, twin := range twins {
53-
// TODO: this is only returning active deployments,
54-
// cause when deprovision the workload is removed from the key list.
55-
deploymentList, err := deps.Provision.List(ctx, twin)
52+
deploymentList, err := deps.Storage.GetDeployments(ctx, twin)
5653
if err != nil {
5754
return ListResponse{}, err
5855
}
@@ -76,3 +73,4 @@ func List(ctx context.Context, deps Deps, req ListRequest) (ListResponse, error)
7673

7774
return ListResponse{Deployments: deployments}, nil
7875
}
76+

pkg/provision.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,15 @@ type Provision interface {
2121
ListTwins() ([]uint32, error)
2222
ListPublicIPs() ([]string, error)
2323
ListPrivateIPs(twin uint32, network gridtypes.Name) ([]string, error)
24+
// GetDeployment returns a deployment including soft-deleted ones.
25+
GetDeployment(twin uint32, contractID uint64) (gridtypes.Deployment, error)
26+
// GetDeployments returns all deployments for a twin including soft-deleted ones.
27+
GetDeployments(twin uint32) ([]gridtypes.Deployment, error)
28+
// GetTwins returns all twins including soft-deleted ones.
29+
GetTwins() ([]uint32, error)
30+
// GetWorkload returns the latest workload state by name including soft-deleted ones.
31+
// Returns (workload, true, nil) if found, (zero, false, nil) if not found.
32+
GetWorkload(twin uint32, contractID uint64, name gridtypes.Name) (gridtypes.Workload, bool, error)
2433
}
2534

2635
type Statistics interface {

pkg/provision/debug.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package provision
2+
3+
import "github.com/threefoldtech/zosbase/pkg/gridtypes"
4+
5+
func (e *NativeEngine) GetDeployment(twin uint32, contractID uint64) (gridtypes.Deployment, error) {
6+
return e.storage.Get(twin, contractID, WithDeleted())
7+
}
8+
9+
func (e *NativeEngine) GetDeployments(twin uint32) ([]gridtypes.Deployment, error) {
10+
ids, err := e.storage.ByTwin(twin, WithDeleted())
11+
if err != nil {
12+
return nil, err
13+
}
14+
deployments := make([]gridtypes.Deployment, 0, len(ids))
15+
for _, id := range ids {
16+
dep, err := e.storage.Get(twin, id, WithDeleted())
17+
if err != nil {
18+
return nil, err
19+
}
20+
deployments = append(deployments, dep)
21+
}
22+
return deployments, nil
23+
}
24+
25+
func (e *NativeEngine) GetTwins() ([]uint32, error) {
26+
return e.storage.Twins(WithDeleted())
27+
}
28+
29+
func (e *NativeEngine) GetWorkload(twin uint32, contractID uint64, name gridtypes.Name) (gridtypes.Workload, bool, error) {
30+
dep, err := e.storage.Get(twin, contractID, WithDeleted())
31+
if err != nil {
32+
return gridtypes.Workload{}, false, err
33+
}
34+
for i := range dep.Workloads {
35+
if dep.Workloads[i].Name == name {
36+
return dep.Workloads[i], true, nil
37+
}
38+
}
39+
wl, err := e.storage.Current(twin, contractID, name, WithDeleted())
40+
if err != nil {
41+
return gridtypes.Workload{}, false, nil // not found, no error
42+
}
43+
return wl, true, nil
44+
}

pkg/provision/interface.go

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,19 @@ type StorageCapacity struct {
110110
// and or workload that returns true from the capacity calculation.
111111
type Exclude = func(dl *gridtypes.Deployment, wl *gridtypes.Workload) bool
112112

113+
// QueryOpt is a functional option for Storage query methods
114+
type QueryOpt func(*QueryOpts)
115+
116+
// QueryOpts holds query options for Storage methods
117+
type QueryOpts struct {
118+
Deleted bool
119+
}
120+
121+
// WithDeleted returns a QueryOpt that includes soft-deleted items in query results
122+
func WithDeleted() QueryOpt {
123+
return func(o *QueryOpts) { o.Deleted = true }
124+
}
125+
113126
// Storage interface
114127
type Storage interface {
115128
// Create a new deployment in storage, it sets the initial transactions
@@ -120,7 +133,7 @@ type Storage interface {
120133
// Delete deletes a deployment from storage.
121134
Delete(twin uint32, deployment uint64) error
122135
// Get gets the current state of a deployment from storage
123-
Get(twin uint32, deployment uint64) (gridtypes.Deployment, error)
136+
Get(twin uint32, deployment uint64, opts ...QueryOpt) (gridtypes.Deployment, error)
124137
// Error sets global deployment error
125138
Error(twin uint32, deployment uint64, err error) error
126139
// Add workload to deployment, if no active deployment exists with same name
@@ -132,11 +145,11 @@ type Storage interface {
132145
// Changes return all the historic transactions of a deployment
133146
Changes(twin uint32, deployment uint64) (changes []gridtypes.Workload, err error)
134147
// Current gets last state of a workload by name
135-
Current(twin uint32, deployment uint64, name gridtypes.Name) (gridtypes.Workload, error)
148+
Current(twin uint32, deployment uint64, name gridtypes.Name, opts ...QueryOpt) (gridtypes.Workload, error)
136149
// Twins list twins in storage
137-
Twins() ([]uint32, error)
150+
Twins(opts ...QueryOpt) ([]uint32, error)
138151
// ByTwin return list of deployments for a twin
139-
ByTwin(twin uint32) ([]uint64, error)
152+
ByTwin(twin uint32, opts ...QueryOpt) ([]uint64, error)
140153
// return total capacity and active deployments
141154
Capacity(exclude ...Exclude) (StorageCapacity, error)
142155
}

0 commit comments

Comments
 (0)