Skip to content

Commit 9f83e67

Browse files
authored
feat: Add 'MemoryStore' (#602)
Features: - Add `MemoryStore` I submitted a pull request for MemoryStore to `oras-credentials-go` a week ago. However, the repository has since been deprecated. I've created an identical PR to [this one](oras-project/oras-credentials-go#92). Reference Issue: [Here](oras-project/oras-credentials-go#89) Signed-off-by: Uanid <[email protected]>
1 parent 577bffe commit 9f83e67

File tree

2 files changed

+283
-0
lines changed

2 files changed

+283
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
Copyright The ORAS Authors.
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.
14+
*/
15+
16+
package credentials
17+
18+
import (
19+
"context"
20+
"sync"
21+
22+
"oras.land/oras-go/v2/registry/remote/auth"
23+
)
24+
25+
// MemoryStore is a store that keeps credentials in memory.
26+
type MemoryStore struct {
27+
store sync.Map
28+
}
29+
30+
// NewMemoryStore creates a new in-memory credentials store.
31+
func NewMemoryStore() *MemoryStore {
32+
return &MemoryStore{}
33+
}
34+
35+
// Get retrieves credentials from the store for the given server address.
36+
func (ms *MemoryStore) Get(_ context.Context, serverAddress string) (auth.Credential, error) {
37+
cred, found := ms.store.Load(serverAddress)
38+
if !found {
39+
return auth.EmptyCredential, nil
40+
}
41+
return cred.(auth.Credential), nil
42+
}
43+
44+
// Put saves credentials into the store for the given server address.
45+
func (ms *MemoryStore) Put(_ context.Context, serverAddress string, cred auth.Credential) error {
46+
ms.store.Store(serverAddress, cred)
47+
return nil
48+
}
49+
50+
// Delete removes credentials from the store for the given server address.
51+
func (ms *MemoryStore) Delete(_ context.Context, serverAddress string) error {
52+
ms.store.Delete(serverAddress)
53+
return nil
54+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
/*
2+
Copyright The ORAS Authors.
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.
14+
*/
15+
16+
package credentials
17+
18+
import (
19+
"context"
20+
"reflect"
21+
"testing"
22+
23+
"oras.land/oras-go/v2/registry/remote/auth"
24+
)
25+
26+
func TestMemoryStore_Get_notExistRecord(t *testing.T) {
27+
ctx := context.Background()
28+
ms := NewMemoryStore()
29+
30+
serverAddress := "registry.example.com"
31+
got, err := ms.Get(ctx, serverAddress)
32+
if err != nil {
33+
t.Errorf("MemoryStore.Get() error = %v", err)
34+
return
35+
}
36+
if !reflect.DeepEqual(got, auth.EmptyCredential) {
37+
t.Errorf("MemoryStore.Get() = %v, want %v", got, auth.EmptyCredential)
38+
}
39+
}
40+
41+
func TestMemoryStore_Get_validRecord(t *testing.T) {
42+
ctx := context.Background()
43+
ms := NewMemoryStore()
44+
45+
serverAddress := "registry.example.com"
46+
want := auth.Credential{
47+
Username: "username",
48+
Password: "password",
49+
RefreshToken: "identity_token",
50+
AccessToken: "registry_token",
51+
}
52+
ms.store.Store(serverAddress, want)
53+
54+
got, err := ms.Get(ctx, serverAddress)
55+
if err != nil {
56+
t.Errorf("MemoryStore.Get() error = %v", err)
57+
return
58+
}
59+
if !reflect.DeepEqual(got, want) {
60+
t.Errorf("MemoryStore.Get() = %v, want %v", got, want)
61+
}
62+
}
63+
64+
func TestMemoryStore_Put_addNew(t *testing.T) {
65+
ctx := context.Background()
66+
ms := NewMemoryStore()
67+
68+
// Test Put
69+
server1 := "registry.example.com"
70+
cred1 := auth.Credential{
71+
Username: "username",
72+
Password: "password",
73+
RefreshToken: "identity_token",
74+
AccessToken: "registry_token",
75+
}
76+
if err := ms.Put(ctx, server1, cred1); err != nil {
77+
t.Errorf("MemoryStore.Put() error = %v", err)
78+
return
79+
}
80+
81+
server2 := "registry2.example.com"
82+
cred2 := auth.Credential{
83+
Username: "username2",
84+
Password: "password2",
85+
RefreshToken: "identity_token2",
86+
AccessToken: "registry_token2",
87+
}
88+
if err := ms.Put(ctx, server2, cred2); err != nil {
89+
t.Errorf("MemoryStore.Put() error = %v", err)
90+
return
91+
}
92+
93+
// Verify Content
94+
got1, err := ms.Get(ctx, server1)
95+
if err != nil {
96+
t.Errorf("MemoryStore.Get() error = %v", err)
97+
return
98+
}
99+
if !reflect.DeepEqual(got1, cred1) {
100+
t.Errorf("MemoryStore.Get() = %v, want %v", got1, cred1)
101+
return
102+
}
103+
104+
got2, err := ms.Get(ctx, server2)
105+
if err != nil {
106+
t.Errorf("MemoryStore.Get() error = %v", err)
107+
return
108+
}
109+
if !reflect.DeepEqual(got2, cred2) {
110+
t.Errorf("MemoryStore.Get() = %v, want %v", got2, cred2)
111+
return
112+
}
113+
}
114+
115+
func TestMemoryStore_Put_update(t *testing.T) {
116+
ctx := context.Background()
117+
ms := NewMemoryStore()
118+
119+
// Test Put
120+
serverAddress := "registry.example.com"
121+
cred1 := auth.Credential{
122+
Username: "username",
123+
Password: "password",
124+
RefreshToken: "identity_token",
125+
AccessToken: "registry_token",
126+
}
127+
if err := ms.Put(ctx, serverAddress, cred1); err != nil {
128+
t.Errorf("MemoryStore.Put() error = %v", err)
129+
return
130+
}
131+
132+
cred2 := auth.Credential{
133+
Username: "username2",
134+
Password: "password2",
135+
RefreshToken: "identity_token2",
136+
AccessToken: "registry_token2",
137+
}
138+
if err := ms.Put(ctx, serverAddress, cred2); err != nil {
139+
t.Errorf("MemoryStore.Put() error = %v", err)
140+
return
141+
}
142+
143+
got, err := ms.Get(ctx, serverAddress)
144+
if err != nil {
145+
t.Errorf("MemoryStore.Get() error = %v", err)
146+
return
147+
}
148+
if !reflect.DeepEqual(got, cred2) {
149+
t.Errorf("MemoryStore.Get() = %v, want %v", got, cred2)
150+
return
151+
}
152+
}
153+
154+
func TestMemoryStore_Delete_existRecord(t *testing.T) {
155+
ctx := context.Background()
156+
ms := NewMemoryStore()
157+
158+
// Test Put
159+
serverAddress := "registry.example.com"
160+
cred := auth.Credential{
161+
Username: "username",
162+
Password: "password",
163+
RefreshToken: "identity_token",
164+
AccessToken: "registry_token",
165+
}
166+
if err := ms.Put(ctx, serverAddress, cred); err != nil {
167+
t.Errorf("MemoryStore.Put() error = %v", err)
168+
return
169+
}
170+
171+
// Test Get
172+
got, err := ms.Get(ctx, serverAddress)
173+
if err != nil {
174+
t.Errorf("MemoryStore.Get() error = %v", err)
175+
return
176+
}
177+
if !reflect.DeepEqual(got, cred) {
178+
t.Errorf("MemoryStore.Get(%s) = %v, want %v", serverAddress, got, cred)
179+
return
180+
}
181+
182+
// Test Delete
183+
if err := ms.Delete(ctx, serverAddress); err != nil {
184+
t.Errorf("MemoryStore.Delete() error = %v", err)
185+
return
186+
}
187+
188+
// Test Get again
189+
got, err = ms.Get(ctx, serverAddress)
190+
if err != nil {
191+
t.Errorf("MemoryStore.Get() error = %v", err)
192+
return
193+
}
194+
if !reflect.DeepEqual(got, auth.EmptyCredential) {
195+
t.Errorf("MemoryStore.Get() = %v, want %v", got, auth.EmptyCredential)
196+
return
197+
}
198+
}
199+
200+
func TestMemoryStore_Delete_notExistRecord(t *testing.T) {
201+
ctx := context.Background()
202+
ms := NewMemoryStore()
203+
204+
// Test Put
205+
serverAddress := "registry.example.com"
206+
cred := auth.Credential{
207+
Username: "username",
208+
Password: "password",
209+
RefreshToken: "identity_token",
210+
AccessToken: "registry_token",
211+
}
212+
if err := ms.Put(ctx, serverAddress, cred); err != nil {
213+
t.Errorf("MemoryStore.Put() error = %v", err)
214+
return
215+
}
216+
217+
// Test Delete
218+
if err := ms.Delete(ctx, serverAddress); err != nil {
219+
t.Errorf("MemoryStore.Delete() error = %v", err)
220+
return
221+
}
222+
223+
// Test Delete again
224+
// Expect no error if target record does not exist
225+
if err := ms.Delete(ctx, serverAddress); err != nil {
226+
t.Errorf("MemoryStore.Delete() error = %v", err)
227+
return
228+
}
229+
}

0 commit comments

Comments
 (0)