Skip to content

Commit d779ca9

Browse files
authored
Reintroduce pkg/util/modules, in place of dskit/modules (#4617)
Signed-off-by: Arve Knudsen <[email protected]>
1 parent 5d79d2f commit d779ca9

File tree

8 files changed

+236
-9
lines changed

8 files changed

+236
-9
lines changed

pkg/cortex/cortex.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import (
1414
"github.com/go-kit/log/level"
1515
"github.com/grafana/dskit/flagext"
1616
"github.com/grafana/dskit/kv/memberlist"
17-
"github.com/grafana/dskit/modules"
1817
"github.com/grafana/dskit/services"
1918
"github.com/pkg/errors"
2019
"github.com/prometheus/client_golang/prometheus"
@@ -59,6 +58,7 @@ import (
5958
"github.com/cortexproject/cortex/pkg/util/fakeauth"
6059
"github.com/cortexproject/cortex/pkg/util/grpcutil"
6160
util_log "github.com/cortexproject/cortex/pkg/util/log"
61+
"github.com/cortexproject/cortex/pkg/util/modules"
6262
"github.com/cortexproject/cortex/pkg/util/process"
6363
"github.com/cortexproject/cortex/pkg/util/runtimeconfig"
6464
"github.com/cortexproject/cortex/pkg/util/validation"

pkg/cortex/modules.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"github.com/go-kit/log/level"
1212
"github.com/grafana/dskit/kv/codec"
1313
"github.com/grafana/dskit/kv/memberlist"
14-
"github.com/grafana/dskit/modules"
1514
"github.com/grafana/dskit/services"
1615
"github.com/opentracing-contrib/go-stdlib/nethttp"
1716
"github.com/opentracing/opentracing-go"
@@ -47,6 +46,7 @@ import (
4746
"github.com/cortexproject/cortex/pkg/scheduler"
4847
"github.com/cortexproject/cortex/pkg/storegateway"
4948
util_log "github.com/cortexproject/cortex/pkg/util/log"
49+
"github.com/cortexproject/cortex/pkg/util/modules"
5050
"github.com/cortexproject/cortex/pkg/util/runtimeconfig"
5151
"github.com/cortexproject/cortex/pkg/util/validation"
5252
)

pkg/flusher/flusher.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ import (
77

88
"github.com/go-kit/log"
99
"github.com/go-kit/log/level"
10-
"github.com/grafana/dskit/modules"
1110
"github.com/grafana/dskit/services"
1211
"github.com/pkg/errors"
1312
"github.com/prometheus/client_golang/prometheus"
1413

1514
"github.com/cortexproject/cortex/pkg/ingester"
15+
"github.com/cortexproject/cortex/pkg/util/modules"
1616
"github.com/cortexproject/cortex/pkg/util/validation"
1717
)
1818

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@ import (
66

77
"github.com/go-kit/log"
88
"github.com/go-kit/log/level"
9-
"github.com/pkg/errors"
10-
119
"github.com/grafana/dskit/services"
10+
"github.com/pkg/errors"
1211
)
1312

1413
// ErrStopProcess is the error returned by a service as a hint to stop the server entirely.
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package modules
22

33
import (
44
"github.com/go-kit/log"
5-
65
"github.com/grafana/dskit/services"
76
)
87

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@ import (
55
"sort"
66

77
"github.com/go-kit/log"
8-
"github.com/pkg/errors"
9-
108
"github.com/grafana/dskit/services"
9+
"github.com/pkg/errors"
1110
)
1211

1312
// module is the basic building block of the application

pkg/util/modules/modules_test.go

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
package modules
2+
3+
import (
4+
"context"
5+
"errors"
6+
"fmt"
7+
"testing"
8+
"time"
9+
10+
"github.com/go-kit/log"
11+
"github.com/grafana/dskit/services"
12+
"github.com/stretchr/testify/assert"
13+
"github.com/stretchr/testify/require"
14+
)
15+
16+
func mockInitFunc() (services.Service, error) { return services.NewIdleService(nil, nil), nil }
17+
18+
func mockInitFuncFail() (services.Service, error) { return nil, errors.New("Error") }
19+
20+
func TestDependencies(t *testing.T) {
21+
var testModules = map[string]module{
22+
"serviceA": {
23+
initFn: mockInitFunc,
24+
},
25+
26+
"serviceB": {
27+
initFn: mockInitFunc,
28+
},
29+
30+
"serviceC": {
31+
initFn: mockInitFunc,
32+
},
33+
34+
"serviceD": {
35+
initFn: mockInitFuncFail,
36+
},
37+
}
38+
39+
mm := NewManager(log.NewNopLogger())
40+
for name, mod := range testModules {
41+
mm.RegisterModule(name, mod.initFn)
42+
}
43+
assert.NoError(t, mm.AddDependency("serviceB", "serviceA"))
44+
assert.NoError(t, mm.AddDependency("serviceC", "serviceB"))
45+
assert.Equal(t, mm.modules["serviceB"].deps, []string{"serviceA"})
46+
47+
invDeps := mm.findInverseDependencies("serviceA", []string{"serviceB", "serviceC"})
48+
require.Len(t, invDeps, 1)
49+
assert.Equal(t, invDeps[0], "serviceB")
50+
51+
// Test unknown module
52+
svc, err := mm.InitModuleServices("service_unknown")
53+
assert.Error(t, err, fmt.Errorf("unrecognised module name: service_unknown"))
54+
assert.Empty(t, svc)
55+
56+
// Test init failure
57+
svc, err = mm.InitModuleServices("serviceD")
58+
assert.Error(t, err)
59+
assert.Empty(t, svc)
60+
61+
// Test loading several modules
62+
svc, err = mm.InitModuleServices("serviceA", "serviceB")
63+
assert.Nil(t, err)
64+
assert.Equal(t, 2, len(svc))
65+
66+
svc, err = mm.InitModuleServices("serviceC")
67+
assert.NoError(t, err)
68+
assert.Equal(t, 3, len(svc))
69+
70+
// Test loading of the module second time - should produce the same set of services, but new instances.
71+
svc2, err := mm.InitModuleServices("serviceC")
72+
assert.NoError(t, err)
73+
assert.Equal(t, 3, len(svc))
74+
assert.NotEqual(t, svc, svc2)
75+
}
76+
77+
func TestRegisterModuleDefaultsToUserVisible(t *testing.T) {
78+
sut := NewManager(log.NewNopLogger())
79+
sut.RegisterModule("module1", mockInitFunc)
80+
81+
m := sut.modules["module1"]
82+
83+
assert.NotNil(t, mockInitFunc, m.initFn, "initFn not assigned")
84+
assert.True(t, m.userVisible, "module should be user visible")
85+
}
86+
87+
func TestFunctionalOptAtTheEndWins(t *testing.T) {
88+
userVisibleMod := func(option *module) {
89+
option.userVisible = true
90+
}
91+
sut := NewManager(log.NewNopLogger())
92+
sut.RegisterModule("mod1", mockInitFunc, UserInvisibleModule, userVisibleMod, UserInvisibleModule)
93+
94+
m := sut.modules["mod1"]
95+
96+
assert.NotNil(t, mockInitFunc, m.initFn, "initFn not assigned")
97+
assert.False(t, m.userVisible, "module should be internal")
98+
}
99+
100+
func TestGetAllUserVisibleModulesNames(t *testing.T) {
101+
sut := NewManager(log.NewNopLogger())
102+
sut.RegisterModule("userVisible3", mockInitFunc)
103+
sut.RegisterModule("userVisible2", mockInitFunc)
104+
sut.RegisterModule("userVisible1", mockInitFunc)
105+
sut.RegisterModule("internal1", mockInitFunc, UserInvisibleModule)
106+
sut.RegisterModule("internal2", mockInitFunc, UserInvisibleModule)
107+
108+
pm := sut.UserVisibleModuleNames()
109+
110+
assert.Equal(t, []string{"userVisible1", "userVisible2", "userVisible3"}, pm, "module list contains wrong element and/or not sorted")
111+
}
112+
113+
func TestGetAllUserVisibleModulesNamesHasNoDupWithDependency(t *testing.T) {
114+
sut := NewManager(log.NewNopLogger())
115+
sut.RegisterModule("userVisible1", mockInitFunc)
116+
sut.RegisterModule("userVisible2", mockInitFunc)
117+
sut.RegisterModule("userVisible3", mockInitFunc)
118+
119+
assert.NoError(t, sut.AddDependency("userVisible1", "userVisible2", "userVisible3"))
120+
121+
pm := sut.UserVisibleModuleNames()
122+
123+
// make sure we don't include any module twice because there is a dependency
124+
assert.Equal(t, []string{"userVisible1", "userVisible2", "userVisible3"}, pm, "module list contains wrong elements and/or not sorted")
125+
}
126+
127+
func TestGetEmptyListWhenThereIsNoUserVisibleModule(t *testing.T) {
128+
sut := NewManager(log.NewNopLogger())
129+
sut.RegisterModule("internal1", mockInitFunc, UserInvisibleModule)
130+
sut.RegisterModule("internal2", mockInitFunc, UserInvisibleModule)
131+
sut.RegisterModule("internal3", mockInitFunc, UserInvisibleModule)
132+
sut.RegisterModule("internal4", mockInitFunc, UserInvisibleModule)
133+
134+
pm := sut.UserVisibleModuleNames()
135+
136+
assert.Len(t, pm, 0, "wrong result slice size")
137+
}
138+
139+
func TestIsUserVisibleModule(t *testing.T) {
140+
userVisibleModName := "userVisible"
141+
internalModName := "internal"
142+
sut := NewManager(log.NewNopLogger())
143+
sut.RegisterModule(userVisibleModName, mockInitFunc)
144+
sut.RegisterModule(internalModName, mockInitFunc, UserInvisibleModule)
145+
146+
var result = sut.IsUserVisibleModule(userVisibleModName)
147+
assert.True(t, result, "module '%v' should be user visible", userVisibleModName)
148+
149+
result = sut.IsUserVisibleModule(internalModName)
150+
assert.False(t, result, "module '%v' should be internal", internalModName)
151+
152+
result = sut.IsUserVisibleModule("ghost")
153+
assert.False(t, result, "expects result be false when module does not exist")
154+
}
155+
156+
func TestIsModuleRegistered(t *testing.T) {
157+
successModule := "successModule"
158+
failureModule := "failureModule"
159+
160+
m := NewManager(log.NewNopLogger())
161+
m.RegisterModule(successModule, mockInitFunc)
162+
163+
var result = m.IsModuleRegistered(successModule)
164+
assert.True(t, result, "module '%v' should be registered", successModule)
165+
166+
result = m.IsModuleRegistered(failureModule)
167+
assert.False(t, result, "module '%v' should NOT be registered", failureModule)
168+
}
169+
170+
func TestDependenciesForModule(t *testing.T) {
171+
m := NewManager(log.NewNopLogger())
172+
m.RegisterModule("test", nil)
173+
m.RegisterModule("dep1", nil)
174+
m.RegisterModule("dep2", nil)
175+
m.RegisterModule("dep3", nil)
176+
177+
require.NoError(t, m.AddDependency("test", "dep2", "dep1"))
178+
require.NoError(t, m.AddDependency("dep1", "dep2"))
179+
require.NoError(t, m.AddDependency("dep2", "dep3"))
180+
181+
deps := m.DependenciesForModule("test")
182+
assert.Equal(t, []string{"dep1", "dep2", "dep3"}, deps)
183+
}
184+
185+
func TestModuleWaitsForAllDependencies(t *testing.T) {
186+
var serviceA services.Service
187+
188+
initA := func() (services.Service, error) {
189+
serviceA = services.NewIdleService(func(serviceContext context.Context) error {
190+
// Slow-starting service. Delay is here to verify that service for C is not started before this service
191+
// has finished starting.
192+
time.Sleep(1 * time.Second)
193+
return nil
194+
}, nil)
195+
196+
return serviceA, nil
197+
}
198+
199+
initC := func() (services.Service, error) {
200+
return services.NewIdleService(func(serviceContext context.Context) error {
201+
// At this point, serviceA should be Running, because "C" depends (indirectly) on "A".
202+
if s := serviceA.State(); s != services.Running {
203+
return fmt.Errorf("serviceA has invalid state: %v", s)
204+
}
205+
return nil
206+
}, nil), nil
207+
}
208+
209+
m := NewManager(log.NewNopLogger())
210+
m.RegisterModule("A", initA)
211+
m.RegisterModule("B", nil)
212+
m.RegisterModule("C", initC)
213+
214+
// C -> B -> A. Even though B has no service, C must still wait for service A to start, before C can start.
215+
require.NoError(t, m.AddDependency("B", "A"))
216+
require.NoError(t, m.AddDependency("C", "B"))
217+
218+
servsMap, err := m.InitModuleServices("C")
219+
require.NoError(t, err)
220+
221+
// Build service manager from services, and start it.
222+
servs := []services.Service(nil)
223+
for _, s := range servsMap {
224+
servs = append(servs, s)
225+
}
226+
227+
servManager, err := services.NewManager(servs...)
228+
require.NoError(t, err)
229+
assert.NoError(t, services.StartManagerAndAwaitHealthy(context.Background(), servManager))
230+
assert.NoError(t, services.StopManagerAndAwaitStopped(context.Background(), servManager))
231+
}

vendor/modules.txt

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)