Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
| ... | ... |
@@ -131,7 +131,7 @@ github.com/containerd/ttrpc f02858b1457c5ca3aaec3a0803eb0d59f96e41d6 |
| 131 | 131 |
github.com/gogo/googleapis 08a7655d27152912db7aaf4f983275eaf8d128ef |
| 132 | 132 |
|
| 133 | 133 |
# cluster |
| 134 |
-github.com/docker/swarmkit 415dc72789e2b733ea884f09188c286ca187d8ec |
|
| 134 |
+github.com/docker/swarmkit 18e7e58ea1a5ec016625a636d0d52500eea123bc |
|
| 135 | 135 |
github.com/gogo/protobuf v1.2.0 |
| 136 | 136 |
github.com/cloudflare/cfssl 1.3.2 |
| 137 | 137 |
github.com/fernet/fernet-go 1b2437bc582b3cfbb341ee5a29f8ef5b42912ff2 |
| ... | ... |
@@ -254,25 +254,23 @@ func (s *Server) UpdateNode(ctx context.Context, request *api.UpdateNodeRequest) |
| 254 | 254 |
}, nil |
| 255 | 255 |
} |
| 256 | 256 |
|
| 257 |
-func removeNodeAttachments(tx store.Tx, nodeID string) error {
|
|
| 258 |
- // orphan the node's attached containers. if we don't do this, the |
|
| 259 |
- // network these attachments are connected to will never be removeable |
|
| 257 |
+func orphanNodeTasks(tx store.Tx, nodeID string) error {
|
|
| 258 |
+ // when a node is deleted, all of its tasks are irrecoverably removed. |
|
| 259 |
+ // additionally, the Dispatcher can no longer be relied on to update the |
|
| 260 |
+ // task status. Therefore, when the node is removed, we must additionally |
|
| 261 |
+ // move all of its assigned tasks to the Orphaned state, so that their |
|
| 262 |
+ // resources can be cleaned up. |
|
| 260 | 263 |
tasks, err := store.FindTasks(tx, store.ByNodeID(nodeID)) |
| 261 | 264 |
if err != nil {
|
| 262 | 265 |
return err |
| 263 | 266 |
} |
| 264 | 267 |
for _, task := range tasks {
|
| 265 |
- // if the task is an attachment, then we just delete it. the allocator |
|
| 266 |
- // will do the heavy lifting. basically, GetAttachment will return the |
|
| 267 |
- // attachment if that's the kind of runtime, or nil if it's not. |
|
| 268 |
- if task.Spec.GetAttachment() != nil {
|
|
| 269 |
- // don't delete the task. instead, update it to `ORPHANED` so that |
|
| 270 |
- // the taskreaper will clean it up. |
|
| 271 |
- task.Status.State = api.TaskStateOrphaned |
|
| 272 |
- if err := store.UpdateTask(tx, task); err != nil {
|
|
| 273 |
- return err |
|
| 274 |
- } |
|
| 268 |
+ task.Status = api.TaskStatus{
|
|
| 269 |
+ Timestamp: gogotypes.TimestampNow(), |
|
| 270 |
+ State: api.TaskStateOrphaned, |
|
| 271 |
+ Message: "Task belonged to a node that has been deleted", |
|
| 275 | 272 |
} |
| 273 |
+ store.UpdateTask(tx, task) |
|
| 276 | 274 |
} |
| 277 | 275 |
return nil |
| 278 | 276 |
} |
| ... | ... |
@@ -342,7 +340,7 @@ func (s *Server) RemoveNode(ctx context.Context, request *api.RemoveNodeRequest) |
| 342 | 342 |
return err |
| 343 | 343 |
} |
| 344 | 344 |
|
| 345 |
- if err := removeNodeAttachments(tx, request.NodeID); err != nil {
|
|
| 345 |
+ if err := orphanNodeTasks(tx, request.NodeID); err != nil {
|
|
| 346 | 346 |
return err |
| 347 | 347 |
} |
| 348 | 348 |
|
| ... | ... |
@@ -392,6 +392,21 @@ func validateConfigRefsSpec(spec api.TaskSpec) error {
|
| 392 | 392 |
return nil |
| 393 | 393 |
} |
| 394 | 394 |
|
| 395 |
+ // check if we're using a config as a CredentialSpec -- if so, we need to |
|
| 396 |
+ // verify |
|
| 397 |
+ var ( |
|
| 398 |
+ credSpecConfig string |
|
| 399 |
+ credSpecConfigFound bool |
|
| 400 |
+ ) |
|
| 401 |
+ if p := container.Privileges; p != nil {
|
|
| 402 |
+ if cs := p.CredentialSpec; cs != nil {
|
|
| 403 |
+ // if there is no config in the credspec, then this will just be |
|
| 404 |
+ // assigned to emptystring anyway, so we don't need to check |
|
| 405 |
+ // existence. |
|
| 406 |
+ credSpecConfig = cs.GetConfig() |
|
| 407 |
+ } |
|
| 408 |
+ } |
|
| 409 |
+ |
|
| 395 | 410 |
// Keep a map to track all the targets that will be exposed |
| 396 | 411 |
// The string returned is only used for logging. It could as well be struct{}{}
|
| 397 | 412 |
existingTargets := make(map[string]string) |
| ... | ... |
@@ -421,6 +436,20 @@ func validateConfigRefsSpec(spec api.TaskSpec) error {
|
| 421 | 421 |
|
| 422 | 422 |
existingTargets[fileName] = configRef.ConfigName |
| 423 | 423 |
} |
| 424 |
+ |
|
| 425 |
+ if configRef.GetRuntime() != nil {
|
|
| 426 |
+ if configRef.ConfigID == credSpecConfig {
|
|
| 427 |
+ credSpecConfigFound = true |
|
| 428 |
+ } |
|
| 429 |
+ } |
|
| 430 |
+ } |
|
| 431 |
+ |
|
| 432 |
+ if credSpecConfig != "" && !credSpecConfigFound {
|
|
| 433 |
+ return status.Errorf( |
|
| 434 |
+ codes.InvalidArgument, |
|
| 435 |
+ "CredentialSpec references config '%s', but that config isn't in config references with RuntimeTarget", |
|
| 436 |
+ credSpecConfig, |
|
| 437 |
+ ) |
|
| 424 | 438 |
} |
| 425 | 439 |
|
| 426 | 440 |
return nil |