@@ -2,8 +2,11 @@ package cmd
22
33import (
44 "bytes"
5+ "fmt"
56 "testing"
67
8+ "github.com/hashicorp/consul/api"
9+ "github.com/ncode/tagit/pkg/consul"
710 "github.com/spf13/cobra"
811 "github.com/stretchr/testify/assert"
912)
@@ -244,19 +247,36 @@ func TestCleanupCmdFlagRetrieval(t *testing.T) {
244247
245248func TestCleanupCmdSuccessFlow (t * testing.T ) {
246249 // Test the successful flow of cleanup command
250+ // Since the actual cleanupCmd creates a real Consul client internally,
251+ // we test with a mock command that simulates the successful path
247252 cmd := & cobra.Command {Use : "tagit" }
248253 cmd .PersistentFlags ().StringP ("consul-addr" , "c" , "127.0.0.1:8500" , "consul address" )
249254 cmd .PersistentFlags ().StringP ("service-id" , "s" , "" , "consul service id" )
250255 cmd .PersistentFlags ().StringP ("script" , "x" , "" , "path to script used to generate tags" )
251256 cmd .PersistentFlags ().StringP ("tag-prefix" , "p" , "tagged" , "prefix to be added to tags" )
252257 cmd .PersistentFlags ().StringP ("token" , "t" , "" , "consul token" )
253258
259+ var logOutput bytes.Buffer
254260 testCleanupCmd := & cobra.Command {
255261 Use : "cleanup" ,
256262 Short : "cleanup removes all services with the tag prefix from a given consul service" ,
257263 RunE : func (cmd * cobra.Command , args []string ) error {
258- // Simulate successful cleanup without actual consul connection
259- // This tests the success path that returns nil
264+ // Verify all required flags are accessible
265+ serviceID := cmd .InheritedFlags ().Lookup ("service-id" ).Value .String ()
266+ tagPrefix := cmd .InheritedFlags ().Lookup ("tag-prefix" ).Value .String ()
267+ consulAddr := cmd .InheritedFlags ().Lookup ("consul-addr" ).Value .String ()
268+ token := cmd .InheritedFlags ().Lookup ("token" ).Value .String ()
269+
270+ // Simulate the logging that would happen
271+ fmt .Fprintf (& logOutput , "Starting tag cleanup, serviceID=%s, tagPrefix=%s, consulAddr=%s\n " ,
272+ serviceID , tagPrefix , consulAddr )
273+
274+ if token != "" {
275+ fmt .Fprintf (& logOutput , "Using token authentication\n " )
276+ }
277+
278+ // Simulate successful cleanup
279+ fmt .Fprintf (& logOutput , "Tag cleanup completed successfully\n " )
260280 return nil
261281 },
262282 }
@@ -268,8 +288,215 @@ func TestCleanupCmdSuccessFlow(t *testing.T) {
268288 "--script=/tmp/test.sh" ,
269289 "--consul-addr=localhost:8500" ,
270290 "--tag-prefix=test" ,
291+ "--token=secret-token" ,
271292 })
272293
273294 err := cmd .Execute ()
274295 assert .NoError (t , err )
296+
297+ // Verify the command would have executed with the right parameters
298+ output := logOutput .String ()
299+ assert .Contains (t , output , "serviceID=test-service" )
300+ assert .Contains (t , output , "tagPrefix=test" )
301+ assert .Contains (t , output , "consulAddr=localhost:8500" )
302+ assert .Contains (t , output , "Using token authentication" )
303+ assert .Contains (t , output , "Tag cleanup completed successfully" )
304+ }
305+
306+ // MockConsulClient for testing
307+ type MockConsulClient struct {
308+ MockAgent consul.Agent
309+ }
310+
311+ func (m * MockConsulClient ) Agent () consul.Agent {
312+ return m .MockAgent
313+ }
314+
315+ // MockAgent implements the Agent interface
316+ type MockAgent struct {
317+ ServiceFunc func (serviceID string , q * api.QueryOptions ) (* api.AgentService , * api.QueryMeta , error )
318+ ServiceRegisterFunc func (reg * api.AgentServiceRegistration ) error
319+ }
320+
321+ func (m * MockAgent ) Service (serviceID string , q * api.QueryOptions ) (* api.AgentService , * api.QueryMeta , error ) {
322+ if m .ServiceFunc != nil {
323+ return m .ServiceFunc (serviceID , q )
324+ }
325+ return & api.AgentService {
326+ ID : "test-service" ,
327+ Service : "test" ,
328+ Tags : []string {"tagged:old" , "other-tag" },
329+ }, nil , nil
330+ }
331+
332+ func (m * MockAgent ) ServiceRegister (reg * api.AgentServiceRegistration ) error {
333+ if m .ServiceRegisterFunc != nil {
334+ return m .ServiceRegisterFunc (reg )
335+ }
336+ return nil
337+ }
338+
339+ func TestCleanupCmdWithMockFactory (t * testing.T ) {
340+ // Save and restore the original factory
341+ originalFactory := consul .Factory
342+ defer func () {
343+ consul .Factory = originalFactory
344+ }()
345+
346+ t .Run ("Successful cleanup with mock" , func (t * testing.T ) {
347+ // Create a mock agent that simulates a service with tags
348+ mockAgent := & MockAgent {
349+ ServiceFunc : func (serviceID string , q * api.QueryOptions ) (* api.AgentService , * api.QueryMeta , error ) {
350+ return & api.AgentService {
351+ ID : serviceID ,
352+ Service : "test" ,
353+ Tags : []string {"tagged-value1" , "tagged-value2" , "other-tag" },
354+ }, nil , nil
355+ },
356+ ServiceRegisterFunc : func (reg * api.AgentServiceRegistration ) error {
357+ // Verify that the tags were cleaned up
358+ assert .Equal (t , "test-service" , reg .ID )
359+ assert .NotContains (t , reg .Tags , "tagged-value1" )
360+ assert .NotContains (t , reg .Tags , "tagged-value2" )
361+ assert .Contains (t , reg .Tags , "other-tag" )
362+ return nil
363+ },
364+ }
365+
366+ // Create mock client with the mock agent
367+ mockClient := & MockConsulClient {
368+ MockAgent : mockAgent ,
369+ }
370+
371+ // Set up the mock factory
372+ mockFactory := & consul.MockFactory {
373+ MockClient : mockClient ,
374+ }
375+ consul .SetFactory (mockFactory )
376+
377+ // Create a new command instance for this test
378+ cmd := & cobra.Command {
379+ Use : "cleanup" ,
380+ RunE : cleanupCmd .RunE ,
381+ }
382+ // Set up parent command for flags inheritance
383+ parent := & cobra.Command {}
384+ parent .PersistentFlags ().String ("consul-addr" , "127.0.0.1:8500" , "" )
385+ parent .PersistentFlags ().String ("token" , "" , "" )
386+ parent .PersistentFlags ().String ("service-id" , "test-service" , "" )
387+ parent .PersistentFlags ().String ("tag-prefix" , "tagged" , "" )
388+ parent .AddCommand (cmd )
389+
390+ // Run the actual cleanup command
391+ err := cmd .RunE (cmd , []string {})
392+ assert .NoError (t , err )
393+ })
394+
395+ t .Run ("Cleanup with connection error" , func (t * testing.T ) {
396+ // Set up a factory that returns an error
397+ mockFactory := & consul.MockFactory {
398+ MockError : fmt .Errorf ("connection failed" ),
399+ }
400+ consul .SetFactory (mockFactory )
401+
402+ // Create a new command instance for this test
403+ cmd := & cobra.Command {
404+ Use : "cleanup" ,
405+ RunE : cleanupCmd .RunE ,
406+ }
407+ // Set up parent command for flags inheritance
408+ parent := & cobra.Command {}
409+ parent .PersistentFlags ().String ("consul-addr" , "127.0.0.1:8500" , "" )
410+ parent .PersistentFlags ().String ("token" , "" , "" )
411+ parent .PersistentFlags ().String ("service-id" , "test-service" , "" )
412+ parent .PersistentFlags ().String ("tag-prefix" , "tagged" , "" )
413+ parent .AddCommand (cmd )
414+
415+ // Run the cleanup command - should fail
416+ err := cmd .RunE (cmd , []string {})
417+ assert .Error (t , err )
418+ })
419+
420+ t .Run ("Cleanup with service not found" , func (t * testing.T ) {
421+ // Create a mock agent that returns nil service
422+ mockAgent := & MockAgent {
423+ ServiceFunc : func (serviceID string , q * api.QueryOptions ) (* api.AgentService , * api.QueryMeta , error ) {
424+ return nil , nil , nil
425+ },
426+ }
427+
428+ // Create mock client with the mock agent
429+ mockClient := & MockConsulClient {
430+ MockAgent : mockAgent ,
431+ }
432+
433+ // Set up the mock factory
434+ mockFactory := & consul.MockFactory {
435+ MockClient : mockClient ,
436+ }
437+ consul .SetFactory (mockFactory )
438+
439+ // Create a new command instance for this test
440+ cmd := & cobra.Command {
441+ Use : "cleanup" ,
442+ RunE : cleanupCmd .RunE ,
443+ }
444+ // Set up parent command for flags inheritance
445+ parent := & cobra.Command {}
446+ parent .PersistentFlags ().String ("consul-addr" , "127.0.0.1:8500" , "" )
447+ parent .PersistentFlags ().String ("token" , "" , "" )
448+ parent .PersistentFlags ().String ("service-id" , "test-service" , "" )
449+ parent .PersistentFlags ().String ("tag-prefix" , "tagged" , "" )
450+ parent .AddCommand (cmd )
451+
452+ // Run the cleanup command - should fail
453+ err := cmd .RunE (cmd , []string {})
454+ assert .Error (t , err )
455+ assert .Contains (t , err .Error (), "service test-service not found" )
456+ })
457+
458+ t .Run ("Cleanup with service register error" , func (t * testing.T ) {
459+ // Create a mock agent that simulates a service with tags but fails on register
460+ mockAgent := & MockAgent {
461+ ServiceFunc : func (serviceID string , q * api.QueryOptions ) (* api.AgentService , * api.QueryMeta , error ) {
462+ return & api.AgentService {
463+ ID : serviceID ,
464+ Service : "test" ,
465+ Tags : []string {"tagged-value1" , "other-tag" },
466+ }, nil , nil
467+ },
468+ ServiceRegisterFunc : func (reg * api.AgentServiceRegistration ) error {
469+ return fmt .Errorf ("failed to register service" )
470+ },
471+ }
472+
473+ // Create mock client with the mock agent
474+ mockClient := & MockConsulClient {
475+ MockAgent : mockAgent ,
476+ }
477+
478+ // Set up the mock factory
479+ mockFactory := & consul.MockFactory {
480+ MockClient : mockClient ,
481+ }
482+ consul .SetFactory (mockFactory )
483+
484+ // Create a new command instance for this test
485+ cmd := & cobra.Command {
486+ Use : "cleanup" ,
487+ RunE : cleanupCmd .RunE ,
488+ }
489+ // Set up parent command for flags inheritance
490+ parent := & cobra.Command {}
491+ parent .PersistentFlags ().String ("consul-addr" , "127.0.0.1:8500" , "" )
492+ parent .PersistentFlags ().String ("token" , "" , "" )
493+ parent .PersistentFlags ().String ("service-id" , "test-service" , "" )
494+ parent .PersistentFlags ().String ("tag-prefix" , "tagged" , "" )
495+ parent .AddCommand (cmd )
496+
497+ // Run the cleanup command - should fail
498+ err := cmd .RunE (cmd , []string {})
499+ assert .Error (t , err )
500+ assert .Contains (t , err .Error (), "failed to clean up tags" )
501+ })
275502}
0 commit comments