Skip to content

Commit 3b8fecd

Browse files
committed
Hack to allow rm to work with oras v2 until oras-project/oras-go#454
Signed-off-by: carabasdaniel <[email protected]>
1 parent 5ac3090 commit 3b8fecd

File tree

1 file changed

+89
-10
lines changed

1 file changed

+89
-10
lines changed

pkg/app/rm.go

+89-10
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
package app
22

33
import (
4+
"encoding/json"
5+
"os"
6+
"path/filepath"
7+
"strings"
8+
9+
"github.com/opcr-io/policy/pkg/oci"
410
"github.com/opcr-io/policy/pkg/parser"
11+
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
512
"github.com/pkg/errors"
6-
"oras.land/oras-go/pkg/content"
713
)
814

915
func (c *PolicyApp) Rm(existingRef string, force bool) error {
@@ -30,35 +36,108 @@ func (c *PolicyApp) Rm(existingRef string, force bool) error {
3036
return nil
3137
}
3238

33-
ociStore, err := content.NewOCI(c.Configuration.PoliciesRoot())
39+
ociClient, err := oci.NewOCI(c.Context, c.Logger, c.getHosts, c.Configuration.PoliciesRoot())
3440
if err != nil {
3541
return err
3642
}
37-
err = ociStore.LoadIndex()
43+
44+
existingRefs, err := ociClient.ListReferences()
3845
if err != nil {
3946
return err
4047
}
4148

42-
existingRefs := ociStore.ListReferences()
43-
44-
_, ok := existingRefs[existingRefParsed]
49+
ref, ok := existingRefs[existingRefParsed]
4550
if !ok {
4651
return errors.Errorf("ref [%s] not found in the local store", existingRef)
4752
}
53+
// attach ref name annotation for comparisson.
54+
ref.Annotations = make(map[string]string)
55+
ref.Annotations[ocispec.AnnotationRefName] = existingRefParsed
4856

49-
ociStore.DeleteReference(existingRefParsed)
57+
err = c.removeFromIndex(ref)
58+
if err != nil {
59+
return err
60+
}
61+
62+
// Reload ociClient with refreshed index to update reference list.
63+
ociClient, err = oci.NewOCI(c.Context, c.Logger, c.getHosts, c.Configuration.PoliciesRoot())
64+
if err != nil {
65+
return err
66+
}
5067

51-
// TODO: if there are no references left to the policy, perhaps delete the descriptor?
52-
// or implement a cleanup command.
68+
updatedRefs, err := ociClient.ListReferences()
69+
if err != nil {
70+
return err
71+
}
72+
// Check if existing images use same digest.
73+
removeBlob := true
74+
for _, v := range updatedRefs {
75+
if v.Digest == ref.Digest {
76+
removeBlob = false
77+
break
78+
}
79+
}
80+
// only remove the blob if not used by another reference.
81+
if removeBlob {
82+
// Hack to remove the existing digest until ocistore deleter is implemented
83+
// https://github.com/oras-project/oras-go/issues/454
84+
digestPath := filepath.Join(strings.Split(ref.Digest.String(), ":")...)
85+
blob := filepath.Join(c.Configuration.PoliciesRoot(), "blobs", digestPath)
86+
err = os.Remove(blob)
87+
if err != nil {
88+
return err
89+
}
90+
}
5391

5492
c.UI.Normal().
5593
WithStringValue("reference", existingRef).
5694
Msg("Removed reference.")
5795

58-
err = ociStore.SaveIndex()
96+
return nil
97+
}
98+
99+
func (c *PolicyApp) removeFromIndex(ref ocispec.Descriptor) error {
100+
101+
type index struct {
102+
Version int `json:"schemaVersion"`
103+
Manifests []ocispec.Descriptor `json:"manifests"`
104+
}
105+
106+
var localIndex index
107+
indexPath := filepath.Join(c.Configuration.PoliciesRoot(), "index.json")
108+
indexBytes, err := os.ReadFile(indexPath)
109+
if err != nil {
110+
return err
111+
}
112+
113+
err = json.Unmarshal(indexBytes, &localIndex)
114+
if err != nil {
115+
return err
116+
}
117+
118+
localIndex.Manifests = removeFromManifests(localIndex.Manifests, ref)
119+
120+
newIndexBytes, err := json.Marshal(localIndex)
59121
if err != nil {
60122
return err
61123
}
62124

125+
err = os.WriteFile(indexPath, newIndexBytes, 0664)
126+
if err != nil {
127+
return err
128+
}
63129
return nil
64130
}
131+
132+
func removeFromManifests(manifests []ocispec.Descriptor, ref ocispec.Descriptor) []ocispec.Descriptor {
133+
newarray := make([]ocispec.Descriptor, len(manifests)-1)
134+
k := 0
135+
for i := 0; i < len(manifests); i++ {
136+
if manifests[i].Digest == ref.Digest && manifests[i].Annotations[ocispec.AnnotationRefName] == ref.Annotations[ocispec.AnnotationRefName] {
137+
continue
138+
}
139+
newarray[k] = manifests[i]
140+
k++
141+
}
142+
return newarray
143+
}

0 commit comments

Comments
 (0)