-
Notifications
You must be signed in to change notification settings - Fork 111
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RSDK-9440 Report machine state
through GetMachineStatus
#4616
base: main
Are you sure you want to change the base?
Changes from all commits
9026f00
53b9d29
4802b8d
8fa9830
c78e16e
62c3f5e
3b9d6b9
d97e583
58b4b94
eacd561
4948b13
d756396
fcf03b5
09b76fd
35f8f3d
e299ab4
19f7940
d68e6f4
2d8bc1b
f997bbb
f97feef
72bada6
fc67364
18555b3
e46aa9d
7f0fffd
da02e54
2c591ad
d5e484f
5bed7f2
e00ad7d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -71,6 +71,12 @@ type Config struct { | |
// Revision contains the current revision of the config. | ||
Revision string | ||
|
||
// Initial represents whether this is an "initial" config passed in by web | ||
// server entrypoint code. If true, the robot will continue to report a state | ||
// of initializing after applying this config. If false, the robot will | ||
// report a state of reconfiguring after applying this config. | ||
Initial bool | ||
|
||
// toCache stores the JSON marshalled version of the config to be cached. It should be a copy of | ||
// the config pulled from cloud with minor changes. | ||
// This version is kept because the config is changed as it moves through the system. | ||
|
@@ -101,6 +107,7 @@ type configData struct { | |
LogConfig []logging.LoggerPatternConfig `json:"log,omitempty"` | ||
Revision string `json:"revision,omitempty"` | ||
MaintenanceConfig *MaintenanceConfig `json:"maintenance,omitempty"` | ||
PackagePath string `json:"package_path,omitempty"` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We were missing some code to marshal and unmarshal the |
||
} | ||
|
||
// AppValidationStatus refers to the. | ||
|
@@ -308,6 +315,7 @@ func (c *Config) UnmarshalJSON(data []byte) error { | |
c.LogConfig = conf.LogConfig | ||
c.Revision = conf.Revision | ||
c.MaintenanceConfig = conf.MaintenanceConfig | ||
c.PackagePath = conf.PackagePath | ||
|
||
return nil | ||
} | ||
|
@@ -340,6 +348,7 @@ func (c Config) MarshalJSON() ([]byte, error) { | |
LogConfig: c.LogConfig, | ||
Revision: c.Revision, | ||
MaintenanceConfig: c.MaintenanceConfig, | ||
PackagePath: c.PackagePath, | ||
}) | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -60,6 +60,12 @@ var ( | |||||
|
||||||
// defaultResourcesTimeout is the default timeout for getting resources. | ||||||
defaultResourcesTimeout = 5 * time.Second | ||||||
|
||||||
// DoNotWaitForRunning should be set only in tests to allow connecting to | ||||||
// still-initializing machines. Note that robot clients in production (not in | ||||||
// a testing environment) will already allow connecting to still-initializing | ||||||
// machines. | ||||||
DoNotWaitForRunning = atomic.Bool{} | ||||||
) | ||||||
|
||||||
// RobotClient satisfies the robot.Robot interface through a gRPC based | ||||||
|
@@ -288,6 +294,41 @@ func New(ctx context.Context, address string, clientLogger logging.ZapCompatible | |||||
return nil, err | ||||||
} | ||||||
|
||||||
// If running in a testing environment, wait for machine to report a state of | ||||||
// running. We often establish connections in tests and expect resources to | ||||||
// be immediately available once the web service has started; resources will | ||||||
// not be available when the machine is still initializing. | ||||||
// | ||||||
// It is expected that golang SDK users will handle lack of resource | ||||||
// availability due to the machine being in an initializing state themselves. | ||||||
// | ||||||
// Allow this behavior to be turned off in some tests that specifically want | ||||||
// to examine the behavior of a machine in an initializing state through the | ||||||
// use of an environment variable. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
if testing.Testing() && !DoNotWaitForRunning.Load() { | ||||||
for { | ||||||
if ctx.Err() != nil { | ||||||
return nil, multierr.Combine(ctx.Err(), rc.conn.Close()) | ||||||
} | ||||||
|
||||||
mStatus, err := rc.MachineStatus(ctx) | ||||||
if err != nil { | ||||||
// Allow for MachineStatus to not be injected/implemented in some tests. | ||||||
if status.Code(err) == codes.Unimplemented { | ||||||
break | ||||||
} | ||||||
// Ignore error from Close and just return original machine status error. | ||||||
utils.UncheckedError(rc.conn.Close()) | ||||||
return nil, err | ||||||
} | ||||||
|
||||||
if mStatus.State == robot.StateRunning { | ||||||
break | ||||||
} | ||||||
time.Sleep(50 * time.Millisecond) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. will this eventually timeout? |
||||||
} | ||||||
} | ||||||
|
||||||
// refresh once to hydrate the robot. | ||||||
if err := rc.Refresh(ctx); err != nil { | ||||||
return nil, multierr.Combine(err, rc.conn.Close()) | ||||||
|
@@ -1115,6 +1156,16 @@ func (rc *RobotClient) MachineStatus(ctx context.Context) (robot.MachineStatus, | |||||
mStatus.Resources = append(mStatus.Resources, resStatus) | ||||||
} | ||||||
|
||||||
switch resp.State { | ||||||
case pb.GetMachineStatusResponse_STATE_UNSPECIFIED: | ||||||
rc.logger.CError(ctx, "received unspecified machine state") | ||||||
mStatus.State = robot.StateUnknown | ||||||
case pb.GetMachineStatusResponse_STATE_INITIALIZING: | ||||||
mStatus.State = robot.StateInitializing | ||||||
case pb.GetMachineStatusResponse_STATE_RUNNING: | ||||||
mStatus.State = robot.StateRunning | ||||||
} | ||||||
|
||||||
return mStatus, nil | ||||||
} | ||||||
|
||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -107,8 +107,11 @@ func TestClientSessionOptions(t *testing.T) { | |
return &dummyEcho{Named: arbName.AsNamed()}, nil | ||
}, | ||
ResourceRPCAPIsFunc: func() []resource.RPCAPI { return nil }, | ||
LoggerFunc: func() logging.Logger { return logger }, | ||
SessMgr: sessMgr, | ||
MachineStatusFunc: func(_ context.Context) (robot.MachineStatus, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I inject an almost identical I thought about placing this functionality in |
||
return robot.MachineStatus{State: robot.StateRunning}, nil | ||
}, | ||
LoggerFunc: func() logging.Logger { return logger }, | ||
SessMgr: sessMgr, | ||
} | ||
|
||
svc := web.New(injectRobot, logger) | ||
|
@@ -129,13 +132,11 @@ func TestClientSessionOptions(t *testing.T) { | |
Disable: true, | ||
}))) | ||
} | ||
roboClient, err := client.New(ctx, addr, logger, opts...) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In three of the client session tests, I had to move the instantiation of the robot client to be below the injection of the session manager. I'd like to meet offline at some point to walk through There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'm fine not touching this in the current PR. But are we currently aware of a reason why There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
As far as I can tell, we only rely on |
||
test.That(t, err, test.ShouldBeNil) | ||
|
||
injectRobot.Mu.Lock() | ||
injectRobot.MachineStatusFunc = func(ctx context.Context) (robot.MachineStatus, error) { | ||
session.SafetyMonitorResourceName(ctx, someTargetName1) | ||
return robot.MachineStatus{}, nil | ||
return robot.MachineStatus{State: robot.StateRunning}, nil | ||
} | ||
injectRobot.Mu.Unlock() | ||
|
||
|
@@ -179,6 +180,8 @@ func TestClientSessionOptions(t *testing.T) { | |
} | ||
sessMgr.mu.Unlock() | ||
|
||
roboClient, err := client.New(ctx, addr, logger, opts...) | ||
test.That(t, err, test.ShouldBeNil) | ||
resp, err := roboClient.MachineStatus(nextCtx) | ||
test.That(t, err, test.ShouldBeNil) | ||
test.That(t, resp, test.ShouldNotBeNil) | ||
|
@@ -289,6 +292,9 @@ func TestClientSessionExpiration(t *testing.T) { | |
ResourceByNameFunc: func(name resource.Name) (resource.Resource, error) { | ||
return &dummyEcho1, nil | ||
}, | ||
MachineStatusFunc: func(_ context.Context) (robot.MachineStatus, error) { | ||
return robot.MachineStatus{State: robot.StateRunning}, nil | ||
}, | ||
ResourceRPCAPIsFunc: func() []resource.RPCAPI { return nil }, | ||
LoggerFunc: func() logging.Logger { return logger }, | ||
SessMgr: sessMgr, | ||
|
@@ -306,8 +312,6 @@ func TestClientSessionExpiration(t *testing.T) { | |
Disable: true, | ||
}))) | ||
} | ||
roboClient, err := client.New(ctx, addr, logger, opts...) | ||
test.That(t, err, test.ShouldBeNil) | ||
|
||
injectRobot.Mu.Lock() | ||
var capSessID uuid.UUID | ||
|
@@ -317,7 +321,7 @@ func TestClientSessionExpiration(t *testing.T) { | |
panic("expected session") | ||
} | ||
capSessID = sess.ID() | ||
return robot.MachineStatus{}, nil | ||
return robot.MachineStatus{State: robot.StateRunning}, nil | ||
} | ||
injectRobot.Mu.Unlock() | ||
|
||
|
@@ -372,6 +376,8 @@ func TestClientSessionExpiration(t *testing.T) { | |
} | ||
sessMgr.mu.Unlock() | ||
|
||
roboClient, err := client.New(ctx, addr, logger, opts...) | ||
test.That(t, err, test.ShouldBeNil) | ||
resp, err := roboClient.MachineStatus(nextCtx) | ||
test.That(t, err, test.ShouldBeNil) | ||
test.That(t, resp, test.ShouldNotBeNil) | ||
|
@@ -480,8 +486,11 @@ func TestClientSessionResume(t *testing.T) { | |
injectRobot := &inject.Robot{ | ||
ResourceNamesFunc: func() []resource.Name { return []resource.Name{} }, | ||
ResourceRPCAPIsFunc: func() []resource.RPCAPI { return nil }, | ||
LoggerFunc: func() logging.Logger { return logger }, | ||
SessMgr: sessMgr, | ||
MachineStatusFunc: func(_ context.Context) (robot.MachineStatus, error) { | ||
return robot.MachineStatus{State: robot.StateRunning}, nil | ||
}, | ||
LoggerFunc: func() logging.Logger { return logger }, | ||
SessMgr: sessMgr, | ||
} | ||
|
||
svc := web.New(injectRobot, logger) | ||
|
@@ -496,8 +505,6 @@ func TestClientSessionResume(t *testing.T) { | |
Disable: true, | ||
}))) | ||
} | ||
roboClient, err := client.New(ctx, addr, logger, opts...) | ||
test.That(t, err, test.ShouldBeNil) | ||
|
||
var capMu sync.Mutex | ||
var startCalled int | ||
|
@@ -536,10 +543,12 @@ func TestClientSessionResume(t *testing.T) { | |
panic("expected session") | ||
} | ||
capSessID = sess.ID() | ||
return robot.MachineStatus{}, nil | ||
return robot.MachineStatus{State: robot.StateRunning}, nil | ||
} | ||
injectRobot.Mu.Unlock() | ||
|
||
roboClient, err := client.New(ctx, addr, logger, opts...) | ||
test.That(t, err, test.ShouldBeNil) | ||
resp, err := roboClient.MachineStatus(nextCtx) | ||
test.That(t, err, test.ShouldBeNil) | ||
test.That(t, resp, test.ShouldNotBeNil) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
?