github.com/choria-io/go-choria@v0.28.1-0.20240416190746-b3bf9c7d5a45/integration/suites/rpcutil/rpcutil_test.go (about) 1 // Copyright (c) 2022, R.I. Pienaar and the Choria Project contributors 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 5 package rpcutil 6 7 import ( 8 "context" 9 "encoding/json" 10 "path/filepath" 11 "sync" 12 "testing" 13 "time" 14 15 "github.com/choria-io/go-choria/build" 16 "github.com/choria-io/go-choria/choria" 17 "github.com/choria-io/go-choria/client/rpcutilclient" 18 "github.com/choria-io/go-choria/config" 19 "github.com/choria-io/go-choria/integration/testbroker" 20 "github.com/choria-io/go-choria/integration/testutil" 21 "github.com/choria-io/go-choria/providers/agent/mcorpc" 22 "github.com/choria-io/go-choria/providers/agent/mcorpc/golang/rpcutil" 23 "github.com/choria-io/go-choria/server" 24 . "github.com/onsi/ginkgo/v2" 25 . "github.com/onsi/gomega" 26 "github.com/onsi/gomega/gbytes" 27 "github.com/sirupsen/logrus" 28 ) 29 30 func TestRPCUtilAgent(t *testing.T) { 31 RegisterFailHandler(Fail) 32 RunSpecs(t, "Integration/rpcutil Agent") 33 } 34 35 var _ = Describe("rpcutil agent", func() { 36 var ( 37 ctx context.Context 38 cancel context.CancelFunc 39 wg sync.WaitGroup 40 srv *server.Instance 41 err error 42 rpcutilAgent *mcorpc.Agent 43 rpcutilClient *rpcutilclient.RpcutilClient 44 brokerLogger *logrus.Logger 45 brokerLogbuff *gbytes.Buffer 46 serverLogbuff *gbytes.Buffer 47 ) 48 49 startServerInstance := func(cfgFile string, logbuff *gbytes.Buffer) (*server.Instance, error) { 50 logger := logrus.New() 51 logger.SetOutput(logbuff) 52 53 srv, err = testutil.StartServerInstance(ctx, &wg, cfgFile, logger, testutil.ServerWithRPCUtilAgent()) 54 Expect(err).ToNot(HaveOccurred()) 55 56 Eventually(logbuff).Should(gbytes.Say("Connected to nats://localhost:4222")) 57 58 rpcutilAgent, err = rpcutil.New(srv.AgentManager()) 59 Expect(err).ToNot(HaveOccurred()) 60 61 return srv, nil 62 } 63 64 createRpcUtilClient := func() (*gbytes.Buffer, *rpcutilclient.RpcutilClient, error) { 65 logBuff, logger := testutil.GbytesLogger(logrus.DebugLevel) 66 67 cfg, err := config.NewConfig("testdata/client.conf") 68 if err != nil { 69 return nil, nil, err 70 } 71 72 cfg.CustomLogger = logger 73 cfg.OverrideCertname = "rip.mcollective" 74 75 fw, err := choria.NewWithConfig(cfg) 76 if err != nil { 77 return nil, nil, err 78 } 79 80 client, err := rpcutilclient.New(fw) 81 if err != nil { 82 return nil, nil, err 83 } 84 85 return logBuff, client, nil 86 } 87 88 BeforeEach(func() { 89 ctx, cancel = context.WithTimeout(context.Background(), 10*time.Second) 90 DeferCleanup(func() { 91 cancel() 92 Eventually(brokerLogbuff, 5).Should(gbytes.Say("Choria Network Broker shut down")) 93 }) 94 95 brokerLogbuff, brokerLogger = testutil.GbytesLogger(logrus.DebugLevel) 96 serverLogbuff = gbytes.NewBuffer() 97 98 _, err := testbroker.StartNetworkBrokerWithConfigFile(ctx, &wg, "testdata/broker.conf", brokerLogger) 99 Expect(err).ToNot(HaveOccurred()) 100 Eventually(brokerLogbuff, 1).Should(gbytes.Say("Server is ready")) 101 102 srv, err = startServerInstance("testdata/server.conf", serverLogbuff) 103 Expect(err).ToNot(HaveOccurred()) 104 Eventually(serverLogbuff).Should(gbytes.Say("Registering new agent rpcutil of type rpcutil")) 105 106 _, rpcutilClient, err = createRpcUtilClient() 107 Expect(err).ToNot(HaveOccurred()) 108 }) 109 110 Describe("Agent", func() { 111 It("Should create all actions we support", func() { 112 Expect(rpcutilAgent.ActionNames()).To(Equal([]string{"agent_inventory", "collective_info", "daemon_stats", "get_config_item", "get_data", "get_fact", "get_facts", "inventory", "ping"})) 113 }) 114 }) 115 116 Describe("agent_inventory action", func() { 117 It("Should get the right inventory", func() { 118 res, err := rpcutilClient.OptionTargets([]string{"localhost"}).AgentInventory().Do(ctx) 119 Expect(err).ToNot(HaveOccurred()) 120 Expect(res.Stats().OKCount()).To(Equal(1)) 121 122 r := rpcutil.AgentInventoryReply{} 123 Expect(res.AllOutputs()[0].ParseAgentInventoryOutput(&r)).ToNot(HaveOccurred()) 124 125 Expect(r.Agents).To(HaveLen(1)) 126 Expect(r.Agents[0].Agent).To(Equal("rpcutil")) 127 Expect(r.Agents[0].Name).To(Equal("rpcutil")) 128 Expect(r.Agents[0].Timeout).To(Equal(2)) 129 }) 130 }) 131 132 Describe("collective_info action", func() { 133 It("Should fetch correct collective info", func() { 134 res, err := rpcutilClient.OptionTargets([]string{"localhost"}).CollectiveInfo().Do(ctx) 135 Expect(err).ToNot(HaveOccurred()) 136 Expect(res.Stats().OKCount()).To(Equal(1)) 137 138 r := res.AllOutputs()[0] 139 Expect(r.Collectives()).To(Equal([]any{"mcollective", "other"})) 140 Expect(r.MainCollective()).To(Equal("mcollective")) 141 }) 142 }) 143 144 Describe("daemon_stats action", func() { 145 It("Should fetch correct instance stats", func() { 146 res, err := rpcutilClient.OptionTargets([]string{"localhost"}).DaemonStats().Do(ctx) 147 Expect(err).ToNot(HaveOccurred()) 148 Expect(res.Stats().OKCount()).To(Equal(1)) 149 150 r := res.AllOutputs()[0] 151 152 Expect(r.Agents()).To(Equal([]any{"rpcutil"})) 153 Expect(r.Version()).To(Equal(build.Version)) 154 path, _ := filepath.Abs("testdata/server.conf") 155 Expect(r.Configfile()).To(Equal(path)) 156 }) 157 }) 158 159 Describe("get_config_item action", func() { 160 It("Should fetch correct item", func() { 161 res, err := rpcutilClient.OptionTargets([]string{"localhost"}).GetConfigItem("classesfile").Do(ctx) 162 Expect(err).ToNot(HaveOccurred()) 163 Expect(res.Stats().OKCount()).To(Equal(1)) 164 165 r := res.AllOutputs()[0] 166 Expect(r.Item()).To(Equal("classesfile")) 167 Expect(r.Value()).To(Equal("testdata/classes.txt")) 168 }) 169 }) 170 171 Describe("get_data action", func() { 172 It("Should get the right data", func() { 173 res, err := rpcutilClient.OptionTargets([]string{"localhost"}).GetData("choria").Do(ctx) 174 Expect(err).ToNot(HaveOccurred()) 175 Expect(res.Stats().OKCount()).To(Equal(1)) 176 177 r := res.AllOutputs()[0].HashMap() 178 179 Expect(r).To(HaveKeyWithValue("classes", []any{"one", "three", "two"})) 180 Expect(r).To(HaveKeyWithValue("classes_count", float64(3))) 181 Expect(r).To(HaveKeyWithValue("connected_broker", "nats://localhost:4222")) 182 }) 183 }) 184 185 Describe("get_fact", func() { 186 It("Should get the right value", func() { 187 res, err := rpcutilClient.OptionTargets([]string{"localhost"}).GetFact("struct.foo").Do(ctx) 188 Expect(err).ToNot(HaveOccurred()) 189 Expect(res.Stats().OKCount()).To(Equal(1)) 190 191 r := res.AllOutputs()[0] 192 Expect(r.Fact()).To(Equal("struct.foo")) 193 Expect(r.Value()).To(Equal("bar")) 194 }) 195 }) 196 197 Describe("get_facts", func() { 198 It("Should get the right value", func() { 199 res, err := rpcutilClient.OptionTargets([]string{"localhost"}).GetFacts("struct.foo,bool").Do(ctx) 200 Expect(err).ToNot(HaveOccurred()) 201 Expect(res.Stats().OKCount()).To(Equal(1)) 202 203 r := res.AllOutputs()[0].Values() 204 Expect(r).To(HaveKeyWithValue("struct.foo", any("bar"))) 205 Expect(r).To(HaveKeyWithValue("bool", any(false))) 206 }) 207 }) 208 209 Describe("inventory action", func() { 210 It("Should retrieve the correct info", func() { 211 res, err := rpcutilClient.OptionTargets([]string{"localhost"}).Inventory().Do(ctx) 212 Expect(err).ToNot(HaveOccurred()) 213 Expect(res.Stats().OKCount()).To(Equal(1)) 214 215 r := res.AllOutputs()[0] 216 Expect(r.Agents()).To(Equal([]any{"rpcutil"})) 217 Expect(r.Classes()).To(Equal([]any{"one", "three", "two"})) 218 Expect(r.Collectives()).To(Equal([]any{"mcollective", "other"})) 219 Expect(r.MainCollective()).To(Equal("mcollective")) 220 Expect(r.DataPlugins()).To(Equal([]any{"choria", "scout"})) 221 fj, err := json.Marshal(r.Facts()) 222 Expect(err).ToNot(HaveOccurred()) 223 Expect(fj).To(MatchJSON(`{"bool":false,"float":1.1,"int":1,"string":"hello world","struct":{"foo":"bar"}}`)) 224 Expect(r.Version()).To(Equal(build.Version)) 225 }) 226 }) 227 228 Describe("ping action", func() { 229 It("Should do the correct pong", func() { 230 res, err := rpcutilClient.OptionTargets([]string{"localhost"}).Ping().Do(ctx) 231 Expect(err).ToNot(HaveOccurred()) 232 Expect(res.Stats().OKCount()).To(Equal(1)) 233 234 r := res.AllOutputs()[0] 235 Expect(err).ToNot(HaveOccurred()) 236 Expect(r.Pong()).To(BeNumerically("==", time.Now().Unix(), 1)) 237 }) 238 }) 239 })