github.com/choria-io/go-choria@v0.28.1-0.20240416190746-b3bf9c7d5a45/providers/agent/mcorpc/ruby/agent_test.go (about)

     1  // Copyright (c) 2020-2022, R.I. Pienaar and the Choria Project contributors
     2  //
     3  // SPDX-License-Identifier: Apache-2.0
     4  
     5  package ruby
     6  
     7  import (
     8  	"context"
     9  	"io"
    10  	"path/filepath"
    11  	"runtime"
    12  
    13  	"github.com/choria-io/go-choria/build"
    14  	"github.com/choria-io/go-choria/choria"
    15  	"github.com/choria-io/go-choria/config"
    16  	"github.com/choria-io/go-choria/inter"
    17  	"github.com/choria-io/go-choria/providers/agent/mcorpc"
    18  	ddl "github.com/choria-io/go-choria/providers/agent/mcorpc/ddl/agent"
    19  	"github.com/golang/mock/gomock"
    20  	. "github.com/onsi/ginkgo/v2"
    21  	. "github.com/onsi/gomega"
    22  	"github.com/sirupsen/logrus"
    23  )
    24  
    25  var _ = Describe("McoRPC/Ruby", func() {
    26  	var (
    27  		mockctl  *gomock.Controller
    28  		agentMgr *MockAgentManager
    29  		cfg      *config.Config
    30  		fw       *choria.Framework
    31  		err      error
    32  		logger   *logrus.Entry
    33  		agent    *mcorpc.Agent
    34  	)
    35  
    36  	BeforeEach(func() {
    37  		build.TLS = "false"
    38  
    39  		l := logrus.New()
    40  		l.Out = io.Discard
    41  		logger = l.WithFields(logrus.Fields{})
    42  
    43  		mockctl = gomock.NewController(GinkgoT())
    44  		agentMgr = NewMockAgentManager(mockctl)
    45  
    46  		cfg = config.NewConfigForTests()
    47  		cfg.DisableSecurityProviderVerify = true
    48  
    49  		fw, err = choria.NewWithConfig(cfg)
    50  		Expect(err).ToNot(HaveOccurred())
    51  
    52  		agentMgr.EXPECT().Choria().Return(fw).AnyTimes()
    53  		agentMgr.EXPECT().Logger().Return(logger).AnyTimes()
    54  	})
    55  
    56  	AfterEach(func() {
    57  		mockctl.Finish()
    58  	})
    59  
    60  	Describe("rubyAction", func() {
    61  		var req *mcorpc.Request
    62  		var rep *mcorpc.Reply
    63  		var ctx context.Context
    64  		var agent *mcorpc.Agent
    65  		var ci inter.ConnectorInfo
    66  
    67  		BeforeEach(func() {
    68  			req = &mcorpc.Request{
    69  				Agent:  "one",
    70  				Action: "status",
    71  			}
    72  
    73  			rep = &mcorpc.Reply{}
    74  			ctx = context.Background()
    75  
    76  			ddl, err := ddl.New("testdata/lib1/mcollective/agent/one.json")
    77  			Expect(err).ToNot(HaveOccurred())
    78  
    79  			agent, err = NewRubyAgent(ddl, agentMgr)
    80  			Expect(err).ToNot(HaveOccurred())
    81  		})
    82  
    83  		It("Should fail when no shim is configured", func() {
    84  			fw.Config.Choria.RubyAgentShim = ""
    85  			rubyAction(ctx, req, rep, agent, ci)
    86  			Expect(rep.Statuscode).To(Equal(mcorpc.Aborted))
    87  			Expect(rep.Statusmsg).To(Equal("Cannot call Ruby action one#status: Ruby compatibility shim was not configured"))
    88  		})
    89  
    90  		It("Should fail when the shim cannot be found", func() {
    91  			fw.Config.Choria.RubyAgentShim = "/nonexisting"
    92  			fw.Config.Choria.RubyAgentConfig = "testdata/shim.cfg"
    93  			rubyAction(ctx, req, rep, agent, ci)
    94  			Expect(rep.Statuscode).To(Equal(mcorpc.Aborted))
    95  			Expect(rep.Statusmsg).To(Equal("Cannot call Ruby action one#status: Ruby compatibility shim was not found in /nonexisting"))
    96  		})
    97  
    98  		It("Should fail without a shim config file", func() {
    99  			fw.Config.Choria.RubyAgentShim = "testdata/nonzero_shim.sh"
   100  			fw.Config.Choria.RubyAgentConfig = ""
   101  
   102  			rubyAction(ctx, req, rep, agent, ci)
   103  			Expect(rep.Statuscode).To(Equal(mcorpc.Aborted))
   104  			Expect(rep.Statusmsg).To(Equal("Cannot call Ruby action one#status: Ruby compatibility shim configuration file not configured"))
   105  		})
   106  
   107  		It("Should fail when a shim config file does not exist", func() {
   108  			fw.Config.Choria.RubyAgentShim = "testdata/nonzero_shim.sh"
   109  			fw.Config.Choria.RubyAgentConfig = "/nonexisting"
   110  
   111  			rubyAction(ctx, req, rep, agent, ci)
   112  			Expect(rep.Statuscode).To(Equal(mcorpc.Aborted))
   113  			Expect(rep.Statusmsg).To(Equal("Cannot call Ruby action one#status: Ruby compatibility shim configuration file was not found in /nonexisting"))
   114  		})
   115  
   116  		It("Should unmarshal the result", func() {
   117  			if runtime.GOOS == "windows" {
   118  				fw.Config.Choria.RubyAgentShim = filepath.Join("testdata", "good_shim_windows.bat")
   119  			} else {
   120  				fw.Config.Choria.RubyAgentShim = filepath.Join("testdata", "good_shim.sh")
   121  			}
   122  
   123  			fw.Config.Choria.RubyAgentConfig = filepath.Join("testdata", "shim.cfg")
   124  
   125  			try := 0
   126  			for try < 5 {
   127  				rubyAction(ctx, req, rep, agent, ci)
   128  				if rep.Statuscode == mcorpc.OK {
   129  					break
   130  				}
   131  				try++
   132  			}
   133  
   134  			Expect(rep.Statusmsg).To(Equal("OK"))
   135  			Expect(rep.Statuscode).To(Equal(mcorpc.OK))
   136  
   137  			d := rep.Data.(map[string]any)
   138  			Expect(d["test"].(string)).To(Equal("ok"))
   139  		})
   140  	})
   141  
   142  	Describe("activationCheck", func() {
   143  		var (
   144  			d   *ddl.DDL
   145  			err error
   146  		)
   147  
   148  		BeforeEach(func() {
   149  			d, err = ddl.New("testdata/lib1/mcollective/agent/one.json")
   150  			Expect(err).ToNot(HaveOccurred())
   151  		})
   152  
   153  		It("Should respect true value activate_agent setting", func() {
   154  			cfg, err := config.NewConfig("testdata/one_agent_enabled.cfg")
   155  			Expect(err).ToNot(HaveOccurred())
   156  			fw.Config = cfg
   157  			Expect(activationCheck(d, agentMgr)()).To(BeTrue())
   158  		})
   159  
   160  		It("Should respect false value activate_agent setting", func() {
   161  			cfg, err := config.NewConfig("testdata/one_agent_disabled.cfg")
   162  			Expect(err).ToNot(HaveOccurred())
   163  			fw.Config = cfg
   164  			Expect(activationCheck(d, agentMgr)()).To(BeFalse())
   165  		})
   166  
   167  		It("Should default to the correct value", func() {
   168  			cfg, err := config.NewConfig("testdata/shim.cfg")
   169  			Expect(err).ToNot(HaveOccurred())
   170  			fw.Config = cfg
   171  			Expect(activationCheck(d, agentMgr)()).To(Equal(activationDefault))
   172  		})
   173  	})
   174  
   175  	Describe("NewRubyAgent", func() {
   176  		It("Should create a shim with all the actions mapped", func() {
   177  			d, err := ddl.New("testdata/lib1/mcollective/agent/one.json")
   178  			Expect(err).ToNot(HaveOccurred())
   179  
   180  			agent, err = NewRubyAgent(d, agentMgr)
   181  			Expect(err).ToNot(HaveOccurred())
   182  
   183  			Expect(agent.ActionNames()).To(Equal(d.ActionNames()))
   184  		})
   185  	})
   186  })