Skip to content

Commit

Permalink
(choria-io#2169) Pass choria federations to external discovery agent
Browse files Browse the repository at this point in the history
  • Loading branch information
vjanelle committed May 3, 2024
1 parent cd5a5a5 commit fd83ec4
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 49 deletions.
1 change: 0 additions & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,6 @@ func NewConfigForTests() *Config {
c.DisableSecurityProviderVerify = true
c.LogFile = "discard"
c.RPCAuthorization = false
c.Choria.FederationCollectives = []string{"alpha", "beta"}

return c
}
Expand Down
16 changes: 15 additions & 1 deletion inter/imocks/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ func WithDDLFiles(kind string, plugin string, path string) fwMockOption {
}
}

func WithFederations(federations []string) fwMockOption {
return func(o *fwMockOpts) {
o.cfg.Choria.FederationCollectives = federations
}
}

func NewFrameworkForTests(ctrl *gomock.Controller, logWriter io.Writer, opts ...fwMockOption) (*MockFramework, *config.Config) {
mopts := &fwMockOpts{
cfg: config.NewConfigForTests(),
Expand All @@ -96,7 +102,15 @@ func NewFrameworkForTests(ctrl *gomock.Controller, logWriter io.Writer, opts ...
fw.EXPECT().Configuration().Return(mopts.cfg).AnyTimes()
fw.EXPECT().Logger(gomock.AssignableToTypeOf("")).Return(logrus.NewEntry(logger)).AnyTimes()
fw.EXPECT().NewRequestID().Return(util.RandomHexString(), nil).AnyTimes()
fw.EXPECT().FederationCollectives().Return([]string{}).AnyTimes()
fw.EXPECT().FederationCollectives().DoAndReturn(
func() []string {
retval := strings.Split(os.Getenv("CHORIA_FED_COLLECTIVE"), ",")
if retval[0] == "" {
return []string{}
} else {
return retval
}
}).AnyTimes()
fw.EXPECT().HasCollective(gomock.AssignableToTypeOf("")).DoAndReturn(func(c string) bool {
for _, collective := range fw.Configuration().Collectives {
if c == collective {
Expand Down
2 changes: 1 addition & 1 deletion providers/discovery/external/external.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func (e *External) Discover(ctx context.Context, opts ...DiscoverOption) (n []st
collective: e.fw.Configuration().MainCollective,
timeout: e.timeout,
command: e.fw.Configuration().Choria.ExternalDiscoveryCommand,
federations: e.fw.Configuration().Choria.FederationCollectives,
federations: e.fw.FederationCollectives(),
do: make(map[string]string),
}

Expand Down
138 changes: 93 additions & 45 deletions providers/discovery/external/external_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,62 +34,110 @@ var _ = Describe("External", func() {
e *External
)

BeforeEach(func() {
mockctl = gomock.NewController(GinkgoT())
fw, cfg = imock.NewFrameworkForTests(mockctl, GinkgoWriter)
cfg.Collectives = []string{"mcollective", "test"}
Context("command without federation", func() {
BeforeEach(func() {
mockctl = gomock.NewController(GinkgoT())
fw, cfg = imock.NewFrameworkForTests(mockctl, GinkgoWriter)
cfg.Collectives = []string{"mcollective", "test"}

e = New(fw)
})
e = New(fw)
})

AfterEach(func() {
mockctl.Finish()
})

Describe("New", func() {
It("Should initialize timeout to default", func() {
Expect(e.timeout).To(Equal(2 * time.Second))
cfg.DiscoveryTimeout = 100
e = New(fw)
Expect(e.timeout).To(Equal(100 * time.Second))
})
})

Describe("Discover", func() {
wd, _ := os.Getwd()
var f *protocol.Filter
BeforeEach(func() {
if runtime.GOOS == "windows" {
Skip("not tested on windows")
}

AfterEach(func() {
mockctl.Finish()
f = protocol.NewFilter()
f.AddAgentFilter("rpcutil")
err := f.AddFactFilter("country", "==", "mt")
Expect(err).ToNot(HaveOccurred())
})
It("Should request and return discovered nodes", func() {
cfg.Choria.ExternalDiscoveryCommand = filepath.Join(wd, "testdata/good.rb")
nodes, err := e.Discover(context.Background(), Filter(f), DiscoveryOptions(map[string]string{"foo": "bar"}))
Expect(err).ToNot(HaveOccurred())
Expect(nodes).To(Equal([]string{"one", "two"}))

cfg.Choria.ExternalDiscoveryCommand = filepath.Join(wd, "testdata/good_with_argument.rb") + " discover --test"
nodes, err = e.Discover(context.Background(), Filter(f), DiscoveryOptions(map[string]string{"foo": "bar"}))
Expect(err).ToNot(HaveOccurred())
Expect(nodes).To(Equal([]string{"one", "two"}))
})

It("Should support command overrides via options", func() {
if runtime.GOOS == "windows" {
Skip("not tested on windows")
}

cfg.Choria.ExternalDiscoveryCommand = filepath.Join(wd, "testdata/missing.rb")
cmd := filepath.Join(wd, "testdata/good_with_argument.rb") + " discover --test"
nodes, err := e.Discover(context.Background(), Filter(f), DiscoveryOptions(map[string]string{"command": cmd, "foo": "bar"}))
Expect(err).ToNot(HaveOccurred())
Expect(nodes).To(Equal([]string{"one", "two"}))
})
})
})
Context("With federation", func() {
BeforeEach(func() {
mockctl = gomock.NewController(GinkgoT())
fw, cfg = imock.NewFrameworkForTests(mockctl, GinkgoWriter, imock.WithFederations([]string{"alpha", "beta"}))
cfg.Collectives = []string{"mcollective", "test"}

Describe("New", func() {
It("Should initialize timeout to default", func() {
Expect(e.timeout).To(Equal(2 * time.Second))
cfg.DiscoveryTimeout = 100
e = New(fw)
Expect(e.timeout).To(Equal(100 * time.Second))
})
})

Describe("Discover", func() {
wd, _ := os.Getwd()
var f *protocol.Filter
BeforeEach(func() {
if runtime.GOOS == "windows" {
Skip("not tested on windows")
}

f = protocol.NewFilter()
f.AddAgentFilter("rpcutil")
err := f.AddFactFilter("country", "==", "mt")
Expect(err).ToNot(HaveOccurred())
AfterEach(func() {
mockctl.Finish()
})
It("Should request and return discovered nodes", func() {
cfg.Choria.ExternalDiscoveryCommand = filepath.Join(wd, "testdata/good.rb")
nodes, err := e.Discover(context.Background(), Filter(f), DiscoveryOptions(map[string]string{"foo": "bar"}))
Expect(err).ToNot(HaveOccurred())
Expect(nodes).To(Equal([]string{"one", "two"}))

cfg.Choria.ExternalDiscoveryCommand = filepath.Join(wd, "testdata/good_with_argument.rb") + " discover --test"
nodes, err = e.Discover(context.Background(), Filter(f), DiscoveryOptions(map[string]string{"foo": "bar"}))
Expect(err).ToNot(HaveOccurred())
Expect(nodes).To(Equal([]string{"one", "two"}))

Describe("New", func() {
It("Should initialize timeout to default", func() {
Expect(e.timeout).To(Equal(2 * time.Second))
cfg.DiscoveryTimeout = 100
e = New(fw)
Expect(e.timeout).To(Equal(100 * time.Second))
})
})

It("Should support command overrides via options", func() {
if runtime.GOOS == "windows" {
Skip("not tested on windows")
}
Describe("Discover", func() {
wd, _ := os.Getwd()
var f *protocol.Filter
BeforeEach(func() {
if runtime.GOOS == "windows" {
Skip("not tested on windows")
}
err := os.Setenv("CHORIA_FED_COLLECTIVE", "alpha,beta")
Expect(err).ToNot(HaveOccurred())

cfg.Choria.ExternalDiscoveryCommand = filepath.Join(wd, "testdata/missing.rb")
cmd := filepath.Join(wd, "testdata/good_with_argument.rb") + " discover --test"
nodes, err := e.Discover(context.Background(), Filter(f), DiscoveryOptions(map[string]string{"command": cmd, "foo": "bar"}))
Expect(err).ToNot(HaveOccurred())
Expect(nodes).To(Equal([]string{"one", "two"}))
f = protocol.NewFilter()
f.AddAgentFilter("rpcutil")
err = f.AddFactFilter("country", "==", "mt")
Expect(err).ToNot(HaveOccurred())
})
It("Should request and return discovered nodes", func() {
cfg.Choria.ExternalDiscoveryCommand = filepath.Join(wd, "testdata/good_with_federation.rb")
nodes, err := e.Discover(context.Background(), Filter(f), DiscoveryOptions(map[string]string{"foo": "bar"}))
Expect(err).ToNot(HaveOccurred())
Expect(nodes).To(Equal([]string{"one", "two"}))
})
})

})
})
2 changes: 1 addition & 1 deletion providers/discovery/external/testdata/good.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def write_output(output)
"identity" => []
},
"collective" => "ginkgo",
"federations" => ["alpha", "beta"],
"federations" => [],
"timeout" => 2,
}

Expand Down
43 changes: 43 additions & 0 deletions providers/discovery/external/testdata/good_with_federation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env ruby

require "json"
require "pp"

def write_output(output)
File.open(ENV["CHORIA_EXTERNAL_REPLY"], "w") {|f|
f.puts(output.to_json)
}
exit
end

if ENV["CHORIA_EXTERNAL_PROTOCOL"] != "io.choria.choria.discovery.v1.external_request"
write_output({"error" => "invalid protocol"})
exit
end

request = JSON.parse(File.read(ENV["CHORIA_EXTERNAL_REQUEST"]))
expected = {
"$schema" => "https://choria.io/schemas/choria/discovery/v1/external_request.json",
"options" => {
"foo" => "bar"
},
"protocol" => "io.choria.choria.discovery.v1.external_request",
"filter" => {
"fact" => [{"fact" => "country", "operator"=>"==","value"=>"mt"}],
"cf_class"=>[],
"agent" => ["rpcutil"],
"compound" => [],
"identity" => []
},
"collective" => "ginkgo",
"federations" => ["alpha", "beta"],
"timeout" => 2,
}

if request != expected
write_output({"error" => "invalid filter received: " + (request.to_a - expected.to_a).pretty_inspect})

# write_output({"error" => "invalid filter received: "+request.pretty_inspect})
else
write_output({"protocol" => "io.choria.choria.discovery.v1.external_reply", "nodes" => ["one","two"]})
end

0 comments on commit fd83ec4

Please sign in to comment.