func (s *ClientSuite) TestActionFinishResultError(c *gc.C) { tag := names.NewActionTag(utils.MustNewUUID().String()) expectedCalls := []jujutesting.StubCall{{ "MachineActions.FinishActions", []interface{}{"", params.ActionExecutionResults{ Results: []params.ActionExecutionResult{{ ActionTag: tag.String(), Status: "", Results: nil, Message: "", }}, }}, }} expectedErr := ¶ms.Error{ Message: "rigged", Code: params.CodeNotAssigned, } var stub jujutesting.Stub apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { stub.AddCall(objType+"."+request, id, arg) c.Check(result, gc.FitsTypeOf, ¶ms.ErrorResults{}) *(result.(*params.ErrorResults)) = params.ErrorResults{ Results: []params.ErrorResult{{expectedErr}}, } return nil }) client := machineactions.NewClient(apiCaller) err := client.ActionFinish(tag, "", nil, "") c.Assert(errors.Cause(err), gc.Equals, expectedErr) stub.CheckCalls(c, expectedCalls) }
func (s *facadeSuite) TestReportKeys(c *gc.C) { stub := new(testing.Stub) apiCaller := basetesting.APICallerFunc(func( objType string, version int, id, request string, args, response interface{}, ) error { c.Check(objType, gc.Equals, "HostKeyReporter") c.Check(version, gc.Equals, 0) c.Check(id, gc.Equals, "") stub.AddCall(request, args) *response.(*params.ErrorResults) = params.ErrorResults{ Results: []params.ErrorResult{{ (*params.Error)(nil), }}, } return nil }) facade := hostkeyreporter.NewFacade(apiCaller) err := facade.ReportKeys("42", []string{"rsa", "dsa"}) c.Assert(err, jc.ErrorIsNil) stub.CheckCalls(c, []testing.StubCall{{ "ReportKeys", []interface{}{params.SSHHostKeySet{ EntityKeys: []params.SSHHostKeys{{ Tag: names.NewMachineTag("42").String(), PublicKeys: []string{"rsa", "dsa"}, }}, }}, }}) }
func (s *ClientSuite) TestGetActionSuccess(c *gc.C) { tag := names.NewActionTag(utils.MustNewUUID().String()) expectedCalls := []jujutesting.StubCall{{ "MachineActions.Actions", []interface{}{"", params.Entities{ Entities: []params.Entity{{Tag: tag.String()}}, }}, }} expectedName := "ack" expectedParams := map[string]interface{}{"floob": "zgloob"} var stub jujutesting.Stub apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { stub.AddCall(objType+"."+request, id, arg) c.Check(result, gc.FitsTypeOf, ¶ms.ActionResults{}) *(result.(*params.ActionResults)) = params.ActionResults{ Results: []params.ActionResult{{ Action: ¶ms.Action{ Name: expectedName, Parameters: expectedParams, }, }}, } return nil }) client := machineactions.NewClient(apiCaller) action, err := client.Action(tag) c.Assert(err, jc.ErrorIsNil) c.Assert(action.Name(), gc.Equals, expectedName) c.Assert(action.Params(), gc.DeepEquals, expectedParams) stub.CheckCalls(c, expectedCalls) }
func (s *ClientSuite) TestRunningActionsResultError(c *gc.C) { tag := names.NewMachineTag(utils.MustNewUUID().String()) expectedCalls := []jujutesting.StubCall{{ "MachineActions.RunningActions", []interface{}{"", params.Entities{ Entities: []params.Entity{{Tag: tag.String()}}, }}, }} expectedErr := ¶ms.Error{ Message: "rigged", Code: params.CodeNotAssigned, } var stub jujutesting.Stub apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { stub.AddCall(objType+"."+request, id, arg) c.Check(result, gc.FitsTypeOf, ¶ms.ActionsByReceivers{}) *(result.(*params.ActionsByReceivers)) = params.ActionsByReceivers{ Actions: []params.ActionsByReceiver{{ Error: expectedErr, }}, } return nil }) client := machineactions.NewClient(apiCaller) action, err := client.RunningActions(tag) c.Assert(errors.Cause(err), gc.Equals, expectedErr) c.Assert(action, gc.IsNil) stub.CheckCalls(c, expectedCalls) }
func (s *FacadeSuite) TestAddress(c *gc.C) { var stub jujutesting.Stub apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { stub.AddCall(objType+"."+request, arg) c.Check(id, gc.Equals, "") *result.(*params.SSHAddressResults) = params.SSHAddressResults{ Results: []params.SSHAddressResult{{Address: "1.1.1.1"}}, } return nil }) facade := sshclient.NewFacade(apiCaller) expectedArg := []interface{}{params.Entities{[]params.Entity{{ names.NewUnitTag("foo/0").String(), }}}} public, err := facade.PublicAddress("foo/0") c.Assert(err, jc.ErrorIsNil) c.Check(public, gc.Equals, "1.1.1.1") stub.CheckCalls(c, []jujutesting.StubCall{{"SSHClient.PublicAddress", expectedArg}}) stub.ResetCalls() private, err := facade.PrivateAddress("foo/0") c.Assert(err, jc.ErrorIsNil) c.Check(private, gc.Equals, "1.1.1.1") stub.CheckCalls(c, []jujutesting.StubCall{{"SSHClient.PrivateAddress", expectedArg}}) }
func (s *ClientSuite) TestActionBeginSuccess(c *gc.C) { tag := names.NewActionTag(utils.MustNewUUID().String()) expectedCalls := []jujutesting.StubCall{{ "MachineActions.BeginActions", []interface{}{"", params.Entities{ Entities: []params.Entity{{Tag: tag.String()}}, }}, }} var stub jujutesting.Stub apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { stub.AddCall(objType+"."+request, id, arg) c.Check(result, gc.FitsTypeOf, ¶ms.ErrorResults{}) *(result.(*params.ErrorResults)) = params.ErrorResults{ Results: []params.ErrorResult{{}}, } return nil }) client := machineactions.NewClient(apiCaller) err := client.ActionBegin(tag) c.Assert(err, jc.ErrorIsNil) stub.CheckCalls(c, expectedCalls) }
func (s *ClientSuite) TestActionFinishSuccess(c *gc.C) { tag := names.NewActionTag(utils.MustNewUUID().String()) status := "stubstatus" actionResults := map[string]interface{}{"stub": "stub"} message := "stubmsg" expectedCalls := []jujutesting.StubCall{{ "MachineActions.FinishActions", []interface{}{"", params.ActionExecutionResults{ Results: []params.ActionExecutionResult{{ ActionTag: tag.String(), Status: status, Results: actionResults, Message: message, }}, }}, }} var stub jujutesting.Stub apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { stub.AddCall(objType+"."+request, id, arg) c.Check(result, gc.FitsTypeOf, ¶ms.ErrorResults{}) *(result.(*params.ErrorResults)) = params.ErrorResults{ Results: []params.ErrorResult{{}}, } return nil }) client := machineactions.NewClient(apiCaller) err := client.ActionFinish(tag, status, actionResults, message) c.Assert(err, jc.ErrorIsNil) stub.CheckCalls(c, expectedCalls) }
func (s *ClientSuite) TestWatchResultError(c *gc.C) { tag := names.NewMachineTag("2") expectErr := ¶ms.Error{ Message: "rigged", Code: params.CodeNotAssigned, } expectedCalls := []jujutesting.StubCall{{ "MachineActions.WatchActionNotifications", []interface{}{"", params.Entities{ Entities: []params.Entity{{Tag: tag.String()}}, }}, }} var stub jujutesting.Stub apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { stub.AddCall(objType+"."+request, id, arg) c.Check(result, gc.FitsTypeOf, ¶ms.StringsWatchResults{}) res := result.(*params.StringsWatchResults) res.Results = make([]params.StringsWatchResult, 1) res.Results[0].Error = expectErr return nil }) client := machineactions.NewClient(apiCaller) w, err := client.WatchActionNotifications(tag) c.Assert(errors.Cause(err), gc.Equals, expectErr) c.Assert(w, gc.IsNil) stub.CheckCalls(c, expectedCalls) }
func (s *ManifoldSuite) TestNewWorkerError(c *gc.C) { fakeClock := &fakeClock{} fakeFacade := &fakeFacade{} fakeAPICaller := &fakeAPICaller{} stub := testing.Stub{} manifold := charmrevisionmanifold.Manifold(charmrevisionmanifold.ManifoldConfig{ APICallerName: "api-caller", ClockName: "clock", NewFacade: func(apiCaller base.APICaller) (charmrevisionmanifold.Facade, error) { stub.AddCall("NewFacade", apiCaller) return fakeFacade, nil }, NewWorker: func(config charmrevision.Config) (worker.Worker, error) { stub.AddCall("NewWorker", config) return nil, errors.New("snrght") }, }) _, err := manifold.Start(dt.StubGetResource(dt.StubResources{ "api-caller": dt.StubResource{Output: fakeAPICaller}, "clock": dt.StubResource{Output: fakeClock}, })) c.Check(err, gc.ErrorMatches, "cannot create worker: snrght") stub.CheckCalls(c, []testing.StubCall{{ "NewFacade", []interface{}{fakeAPICaller}, }, { "NewWorker", []interface{}{charmrevision.Config{ RevisionUpdater: fakeFacade, Clock: fakeClock, }}, }}) }
func (s *ClientSuite) TestModelInfo(c *gc.C) { var stub jujutesting.Stub owner := names.NewUserTag("owner") apiCaller := apitesting.APICallerFunc(func(objType string, v int, id, request string, arg, result interface{}) error { stub.AddCall(objType+"."+request, id, arg) *(result.(*params.MigrationModelInfo)) = params.MigrationModelInfo{ UUID: "uuid", Name: "name", OwnerTag: owner.String(), AgentVersion: version.MustParse("1.2.3"), } return nil }) client := migrationmaster.NewClient(apiCaller, nil) model, err := client.ModelInfo() stub.CheckCalls(c, []jujutesting.StubCall{ {"MigrationMaster.ModelInfo", []interface{}{"", nil}}, }) c.Check(err, jc.ErrorIsNil) c.Check(model, jc.DeepEquals, migration.ModelInfo{ UUID: "uuid", Name: "name", Owner: owner, AgentVersion: version.MustParse("1.2.3"), }) }
func (s *ClientSuite) TestExport(c *gc.C) { var stub jujutesting.Stub apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { stub.AddCall(objType+"."+request, id, arg) out := result.(*params.SerializedModel) *out = params.SerializedModel{ Bytes: []byte("foo"), Charms: []string{"cs:foo-1"}, Tools: []params.SerializedModelTools{{ Version: "2.0.0-trusty-amd64", URI: "/tools/0", }}, } return nil }) client := migrationmaster.NewClient(apiCaller, nil) out, err := client.Export() c.Assert(err, jc.ErrorIsNil) stub.CheckCalls(c, []jujutesting.StubCall{ {"MigrationMaster.Export", []interface{}{"", nil}}, }) c.Assert(out, gc.DeepEquals, migration.SerializedModel{ Bytes: []byte("foo"), Charms: []string{"cs:foo-1"}, Tools: map[version.Binary]string{ version.MustParseBinary("2.0.0-trusty-amd64"): "/tools/0", }, }) }
func (s *ClientSuite) TestRunningActionSuccess(c *gc.C) { tag := names.NewMachineTag(utils.MustNewUUID().String()) expectedCalls := []jujutesting.StubCall{{ "MachineActions.RunningActions", []interface{}{"", params.Entities{ Entities: []params.Entity{{Tag: tag.String()}}, }}, }} actionsList := []params.ActionResult{ {Action: ¶ms.Action{Name: "foo"}}, {Action: ¶ms.Action{Name: "baz"}}, } var stub jujutesting.Stub apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { stub.AddCall(objType+"."+request, id, arg) c.Check(result, gc.FitsTypeOf, ¶ms.ActionsByReceivers{}) *(result.(*params.ActionsByReceivers)) = params.ActionsByReceivers{ Actions: []params.ActionsByReceiver{{ Actions: actionsList, }}, } return nil }) client := machineactions.NewClient(apiCaller) actions, err := client.RunningActions(tag) c.Assert(err, jc.ErrorIsNil) c.Assert(actions, jc.DeepEquals, actionsList) stub.CheckCalls(c, expectedCalls) }
func (s *ClientSuite) TestActionFinishTooManyResults(c *gc.C) { tag := names.NewActionTag(utils.MustNewUUID().String()) expectedCalls := []jujutesting.StubCall{{ "MachineActions.FinishActions", []interface{}{"", params.ActionExecutionResults{ Results: []params.ActionExecutionResult{{ ActionTag: tag.String(), Status: "", Results: nil, Message: "", }}, }}, }} var stub jujutesting.Stub apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { stub.AddCall(objType+"."+request, id, arg) c.Check(result, gc.FitsTypeOf, ¶ms.ErrorResults{}) res := result.(*params.ErrorResults) res.Results = make([]params.ErrorResult, 2) return nil }) client := machineactions.NewClient(apiCaller) err := client.ActionFinish(tag, "", nil, "") c.Assert(err, gc.ErrorMatches, "expected 1 result, got 2") stub.CheckCalls(c, expectedCalls) }
func (s *ClientSuite) getClientAndStub(c *gc.C) (*migrationtarget.Client, *jujutesting.Stub) { var stub jujutesting.Stub apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { stub.AddCall(objType+"."+request, id, arg) return errors.New("boom") }) client := migrationtarget.NewClient(apiCaller) return client, &stub }
func makeStubUploadBinaries(stub *jujutesting.Stub) func(migration.UploadBinariesConfig) error { return func(config migration.UploadBinariesConfig) error { stub.AddCall( "UploadBinaries", config.Charms, config.CharmDownloader, config.Tools, config.ToolsDownloader, ) return nil } }
func (s *ClientSuite) TestReap(c *gc.C) { var stub jujutesting.Stub apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { stub.AddCall(objType+"."+request, id, arg) return nil }) client := migrationmaster.NewClient(apiCaller, nil) err := client.Reap() c.Check(err, jc.ErrorIsNil) stub.CheckCalls(c, []jujutesting.StubCall{ {"MigrationMaster.Reap", []interface{}{"", nil}}, }) }
func (s *ClientSuite) TestPrechecks(c *gc.C) { var stub jujutesting.Stub apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { stub.AddCall(objType+"."+request, id, arg) return errors.New("blam") }) client := migrationmaster.NewClient(apiCaller, nil) err := client.Prechecks() c.Check(err, gc.ErrorMatches, "blam") stub.CheckCalls(c, []jujutesting.StubCall{ {"MigrationMaster.Prechecks", []interface{}{"", nil}}, }) }
func apiCaller(c *gc.C, stub *testing.Stub, set func(interface{}) error) base.APICaller { return basetesting.APICallerFunc(func( objType string, version int, id, request string, args, response interface{}, ) error { c.Check(objType, gc.Equals, "MigrationFlag") c.Check(version, gc.Equals, 0) c.Check(id, gc.Equals, "") stub.AddCall(request, args) return set(response) }) }
func strategyTest(stub *testing.Stub, strategy utils.AttemptStrategy, test func(api.OpenFunc) (api.Connection, error)) (api.Connection, error) { unpatch := testing.PatchValue(apicaller.Strategy, strategy) defer unpatch() return test(func(info *api.Info, opts api.DialOpts) (api.Connection, error) { // copy because I don't trust what might happen to info stub.AddCall("apiOpen", *info, opts) err := stub.NextErr() if err != nil { return nil, err } return &mockConn{stub: stub}, nil }) }
func apiCaller(c *gc.C, stub *testing.Stub, setResult setResultFunc) base.APICaller { return basetesting.APICallerFunc( func(objType string, version int, id, request string, args, response interface{}, ) error { stub.AddCall(objType, version, id, request, args) result, ok := response.(*params.ErrorResults) c.Assert(ok, jc.IsTrue) return setResult(result) }, ) }
func (s *ClientSuite) TestSetPhase(c *gc.C) { var stub jujutesting.Stub apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { stub.AddCall(objType+"."+request, id, arg) return nil }) client := migrationmaster.NewClient(apiCaller) err := client.SetPhase(migration.QUIESCE) c.Assert(err, jc.ErrorIsNil) expectedArg := params.SetMigrationPhaseArgs{Phase: "QUIESCE"} stub.CheckCalls(c, []jujutesting.StubCall{ {"MigrationMaster.SetPhase", []interface{}{"", expectedArg}}, }) }
func makeClient(results params.InitiateMigrationResults) ( *controller.Client, *jujutesting.Stub, ) { var stub jujutesting.Stub apiCaller := apitesting.APICallerFunc( func(objType string, version int, id, request string, arg, result interface{}) error { stub.AddCall(objType+"."+request, arg) out := result.(*params.InitiateMigrationResults) *out = results return nil }, ) client := controller.NewClient(apiCaller) return client, &stub }
func (s *FacadeSuite) TestPublicKeysTargetError(c *gc.C) { var stub jujutesting.Stub apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { stub.AddCall(objType+"."+request, arg) c.Check(id, gc.Equals, "") *result.(*params.SSHPublicKeysResults) = params.SSHPublicKeysResults{ Results: []params.SSHPublicKeysResult{{Error: common.ServerError(errors.New("boom"))}}, } return nil }) facade := sshclient.NewFacade(apiCaller) keys, err := facade.PublicKeys("foo/0") c.Check(keys, gc.IsNil) c.Check(err, gc.ErrorMatches, "boom") }
func checkProxy(c *gc.C, useProxy bool) { var stub jujutesting.Stub apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { stub.AddCall(objType+"."+request, arg) *result.(*params.SSHProxyResult) = params.SSHProxyResult{ UseProxy: useProxy, } return nil }) facade := sshclient.NewFacade(apiCaller) result, err := facade.Proxy() c.Check(err, jc.ErrorIsNil) c.Check(result, gc.Equals, useProxy) stub.CheckCalls(c, []jujutesting.StubCall{{"SSHClient.Proxy", []interface{}{nil}}}) }
func (s *ClientSuite) TestWatch(c *gc.C) { var stub jujutesting.Stub apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { stub.AddCall(objType+"."+request, id, arg) switch request { case "Watch": *(result.(*params.NotifyWatchResult)) = params.NotifyWatchResult{ NotifyWatcherId: "abc", } case "Next": // The full success case is tested in api/watcher. return errors.New("boom") case "Stop": } return nil }) client := migrationminion.NewClient(apiCaller) w, err := client.Watch() c.Assert(err, jc.ErrorIsNil) defer worker.Stop(w) errC := make(chan error) go func() { errC <- w.Wait() }() select { case err := <-errC: c.Assert(err, gc.ErrorMatches, "boom") expectedCalls := []jujutesting.StubCall{ {"Migrationminion.Watch", []interface{}{"", nil}}, {"MigrationStatusWatcher.Next", []interface{}{"abc", nil}}, {"MigrationStatusWatcher.Stop", []interface{}{"abc", nil}}, } // The Stop API call happens in a separate goroutine which // might execute after the worker has exited so wait for the // expected calls to arrive. for a := coretesting.LongAttempt.Start(); a.Next(); { if len(stub.Calls()) >= len(expectedCalls) { return } } stub.CheckCalls(c, expectedCalls) case <-time.After(coretesting.LongWait): c.Fatal("timed out waiting for watcher to die") } }
func (s *ClientSuite) TestExport(c *gc.C) { var stub jujutesting.Stub apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { stub.AddCall(objType+"."+request, id, arg) out := result.(*params.SerializedModel) *out = params.SerializedModel{Bytes: []byte("foo")} return nil }) client := migrationmaster.NewClient(apiCaller) bytes, err := client.Export() c.Assert(err, jc.ErrorIsNil) stub.CheckCalls(c, []jujutesting.StubCall{ {"MigrationMaster.Export", []interface{}{"", nil}}, }) c.Assert(string(bytes), gc.Equals, "foo") }
func (s *ClientSuite) TestImport(c *gc.C) { var stub jujutesting.Stub apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { stub.AddCall(objType+"."+request, id, arg) return errors.New("boom") }) client := migrationtarget.NewClient(apiCaller) err := client.Import([]byte("foo")) expectedArg := params.SerializedModel{Bytes: []byte("foo")} stub.CheckCalls(c, []jujutesting.StubCall{ {"MigrationTarget.Import", []interface{}{"", expectedArg}}, }) c.Assert(err, gc.ErrorMatches, "boom") }
func (s *ClientSuite) TestReport(c *gc.C) { var stub jujutesting.Stub apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { stub.AddCall(objType+"."+request, arg) return nil }) client := migrationminion.NewClient(apiCaller) err := client.Report("id", migration.IMPORT, true) c.Assert(err, jc.ErrorIsNil) stub.CheckCalls(c, []jujutesting.StubCall{ {"MigrationMinion.Report", []interface{}{params.MinionReport{ MigrationId: "id", Phase: "IMPORT", Success: true, }}}, }) }
func (s *FacadeSuite) TestPublicKeys(c *gc.C) { var stub jujutesting.Stub apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { stub.AddCall(objType+"."+request, arg) c.Check(id, gc.Equals, "") *result.(*params.SSHPublicKeysResults) = params.SSHPublicKeysResults{ Results: []params.SSHPublicKeysResult{{PublicKeys: []string{"rsa", "dsa"}}}, } return nil }) facade := sshclient.NewFacade(apiCaller) keys, err := facade.PublicKeys("foo/0") c.Assert(err, jc.ErrorIsNil) c.Check(keys, gc.DeepEquals, []string{"rsa", "dsa"}) stub.CheckCalls(c, []jujutesting.StubCall{{ "SSHClient.PublicKeys", []interface{}{params.Entities{[]params.Entity{{ Tag: names.NewUnitTag("foo/0").String(), }}}}, }}) }
func (s *ClientSuite) TestMinionReports(c *gc.C) { var stub jujutesting.Stub apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { stub.AddCall(objType+"."+request, id, arg) out := result.(*params.MinionReports) *out = params.MinionReports{ MigrationId: "id", Phase: "IMPORT", SuccessCount: 4, UnknownCount: 3, UnknownSample: []string{ names.NewMachineTag("3").String(), names.NewMachineTag("4").String(), names.NewUnitTag("foo/0").String(), }, Failed: []string{ names.NewMachineTag("5").String(), names.NewUnitTag("foo/1").String(), names.NewUnitTag("foo/2").String(), }, } return nil }) client := migrationmaster.NewClient(apiCaller, nil) out, err := client.MinionReports() c.Assert(err, jc.ErrorIsNil) stub.CheckCalls(c, []jujutesting.StubCall{ {"MigrationMaster.MinionReports", []interface{}{"", nil}}, }) c.Assert(out, gc.DeepEquals, migration.MinionReports{ MigrationId: "id", Phase: migration.IMPORT, SuccessCount: 4, UnknownCount: 3, SomeUnknownMachines: []string{"3", "4"}, SomeUnknownUnits: []string{"foo/0"}, FailedMachines: []string{"5"}, FailedUnits: []string{"foo/1", "foo/2"}, }) }