github.imxd.top/hashicorp/consul@v1.4.5/agent/consul/fsm/snapshot_oss.go (about) 1 package fsm 2 3 import ( 4 "github.com/hashicorp/consul/agent/consul/autopilot" 5 "github.com/hashicorp/consul/agent/consul/state" 6 "github.com/hashicorp/consul/agent/structs" 7 "github.com/hashicorp/go-msgpack/codec" 8 "github.com/hashicorp/raft" 9 ) 10 11 func init() { 12 registerPersister(persistOSS) 13 14 registerRestorer(structs.RegisterRequestType, restoreRegistration) 15 registerRestorer(structs.KVSRequestType, restoreKV) 16 registerRestorer(structs.TombstoneRequestType, restoreTombstone) 17 registerRestorer(structs.SessionRequestType, restoreSession) 18 registerRestorer(structs.ACLRequestType, restoreACL) 19 registerRestorer(structs.ACLBootstrapRequestType, restoreACLBootstrap) 20 registerRestorer(structs.CoordinateBatchUpdateType, restoreCoordinates) 21 registerRestorer(structs.PreparedQueryRequestType, restorePreparedQuery) 22 registerRestorer(structs.AutopilotRequestType, restoreAutopilot) 23 registerRestorer(structs.IntentionRequestType, restoreIntention) 24 registerRestorer(structs.ConnectCARequestType, restoreConnectCA) 25 registerRestorer(structs.ConnectCAProviderStateType, restoreConnectCAProviderState) 26 registerRestorer(structs.ConnectCAConfigType, restoreConnectCAConfig) 27 registerRestorer(structs.IndexRequestType, restoreIndex) 28 registerRestorer(structs.ACLTokenSetRequestType, restoreToken) 29 registerRestorer(structs.ACLPolicySetRequestType, restorePolicy) 30 } 31 32 func persistOSS(s *snapshot, sink raft.SnapshotSink, encoder *codec.Encoder) error { 33 if err := s.persistNodes(sink, encoder); err != nil { 34 return err 35 } 36 if err := s.persistSessions(sink, encoder); err != nil { 37 return err 38 } 39 if err := s.persistACLs(sink, encoder); err != nil { 40 return err 41 } 42 if err := s.persistKVs(sink, encoder); err != nil { 43 return err 44 } 45 if err := s.persistTombstones(sink, encoder); err != nil { 46 return err 47 } 48 if err := s.persistPreparedQueries(sink, encoder); err != nil { 49 return err 50 } 51 if err := s.persistAutopilot(sink, encoder); err != nil { 52 return err 53 } 54 if err := s.persistIntentions(sink, encoder); err != nil { 55 return err 56 } 57 if err := s.persistConnectCA(sink, encoder); err != nil { 58 return err 59 } 60 if err := s.persistConnectCAProviderState(sink, encoder); err != nil { 61 return err 62 } 63 if err := s.persistConnectCAConfig(sink, encoder); err != nil { 64 return err 65 } 66 if err := s.persistIndex(sink, encoder); err != nil { 67 return err 68 } 69 return nil 70 } 71 72 func (s *snapshot) persistNodes(sink raft.SnapshotSink, 73 encoder *codec.Encoder) error { 74 75 // Get all the nodes 76 nodes, err := s.state.Nodes() 77 if err != nil { 78 return err 79 } 80 81 // Register each node 82 for node := nodes.Next(); node != nil; node = nodes.Next() { 83 n := node.(*structs.Node) 84 req := structs.RegisterRequest{ 85 ID: n.ID, 86 Node: n.Node, 87 Datacenter: n.Datacenter, 88 Address: n.Address, 89 TaggedAddresses: n.TaggedAddresses, 90 NodeMeta: n.Meta, 91 } 92 93 // Register the node itself 94 if _, err := sink.Write([]byte{byte(structs.RegisterRequestType)}); err != nil { 95 return err 96 } 97 if err := encoder.Encode(&req); err != nil { 98 return err 99 } 100 101 // Register each service this node has 102 services, err := s.state.Services(n.Node) 103 if err != nil { 104 return err 105 } 106 for service := services.Next(); service != nil; service = services.Next() { 107 if _, err := sink.Write([]byte{byte(structs.RegisterRequestType)}); err != nil { 108 return err 109 } 110 req.Service = service.(*structs.ServiceNode).ToNodeService() 111 if err := encoder.Encode(&req); err != nil { 112 return err 113 } 114 } 115 116 // Register each check this node has 117 req.Service = nil 118 checks, err := s.state.Checks(n.Node) 119 if err != nil { 120 return err 121 } 122 for check := checks.Next(); check != nil; check = checks.Next() { 123 if _, err := sink.Write([]byte{byte(structs.RegisterRequestType)}); err != nil { 124 return err 125 } 126 req.Check = check.(*structs.HealthCheck) 127 if err := encoder.Encode(&req); err != nil { 128 return err 129 } 130 } 131 } 132 133 // Save the coordinates separately since they are not part of the 134 // register request interface. To avoid copying them out, we turn 135 // them into batches with a single coordinate each. 136 coords, err := s.state.Coordinates() 137 if err != nil { 138 return err 139 } 140 for coord := coords.Next(); coord != nil; coord = coords.Next() { 141 if _, err := sink.Write([]byte{byte(structs.CoordinateBatchUpdateType)}); err != nil { 142 return err 143 } 144 updates := structs.Coordinates{coord.(*structs.Coordinate)} 145 if err := encoder.Encode(&updates); err != nil { 146 return err 147 } 148 } 149 return nil 150 } 151 152 func (s *snapshot) persistSessions(sink raft.SnapshotSink, 153 encoder *codec.Encoder) error { 154 sessions, err := s.state.Sessions() 155 if err != nil { 156 return err 157 } 158 159 for session := sessions.Next(); session != nil; session = sessions.Next() { 160 if _, err := sink.Write([]byte{byte(structs.SessionRequestType)}); err != nil { 161 return err 162 } 163 if err := encoder.Encode(session.(*structs.Session)); err != nil { 164 return err 165 } 166 } 167 return nil 168 } 169 170 func (s *snapshot) persistACLs(sink raft.SnapshotSink, 171 encoder *codec.Encoder) error { 172 tokens, err := s.state.ACLTokens() 173 if err != nil { 174 return err 175 } 176 177 for token := tokens.Next(); token != nil; token = tokens.Next() { 178 if _, err := sink.Write([]byte{byte(structs.ACLTokenSetRequestType)}); err != nil { 179 return err 180 } 181 if err := encoder.Encode(token.(*structs.ACLToken)); err != nil { 182 return err 183 } 184 } 185 186 policies, err := s.state.ACLPolicies() 187 if err != nil { 188 return err 189 } 190 191 for policy := policies.Next(); policy != nil; policy = policies.Next() { 192 if _, err := sink.Write([]byte{byte(structs.ACLPolicySetRequestType)}); err != nil { 193 return err 194 } 195 if err := encoder.Encode(policy.(*structs.ACLPolicy)); err != nil { 196 return err 197 } 198 } 199 200 return nil 201 } 202 203 func (s *snapshot) persistKVs(sink raft.SnapshotSink, 204 encoder *codec.Encoder) error { 205 entries, err := s.state.KVs() 206 if err != nil { 207 return err 208 } 209 210 for entry := entries.Next(); entry != nil; entry = entries.Next() { 211 if _, err := sink.Write([]byte{byte(structs.KVSRequestType)}); err != nil { 212 return err 213 } 214 if err := encoder.Encode(entry.(*structs.DirEntry)); err != nil { 215 return err 216 } 217 } 218 return nil 219 } 220 221 func (s *snapshot) persistTombstones(sink raft.SnapshotSink, 222 encoder *codec.Encoder) error { 223 stones, err := s.state.Tombstones() 224 if err != nil { 225 return err 226 } 227 228 for stone := stones.Next(); stone != nil; stone = stones.Next() { 229 if _, err := sink.Write([]byte{byte(structs.TombstoneRequestType)}); err != nil { 230 return err 231 } 232 233 // For historical reasons, these are serialized in the snapshots 234 // as KV entries. We want to keep the snapshot format compatible 235 // with pre-0.6 versions for now. 236 s := stone.(*state.Tombstone) 237 fake := &structs.DirEntry{ 238 Key: s.Key, 239 RaftIndex: structs.RaftIndex{ 240 ModifyIndex: s.Index, 241 }, 242 } 243 if err := encoder.Encode(fake); err != nil { 244 return err 245 } 246 } 247 return nil 248 } 249 250 func (s *snapshot) persistPreparedQueries(sink raft.SnapshotSink, 251 encoder *codec.Encoder) error { 252 queries, err := s.state.PreparedQueries() 253 if err != nil { 254 return err 255 } 256 257 for _, query := range queries { 258 if _, err := sink.Write([]byte{byte(structs.PreparedQueryRequestType)}); err != nil { 259 return err 260 } 261 if err := encoder.Encode(query); err != nil { 262 return err 263 } 264 } 265 return nil 266 } 267 268 func (s *snapshot) persistAutopilot(sink raft.SnapshotSink, 269 encoder *codec.Encoder) error { 270 config, err := s.state.Autopilot() 271 if err != nil { 272 return err 273 } 274 // Make sure we don't write a nil config out to a snapshot. 275 if config == nil { 276 return nil 277 } 278 279 if _, err := sink.Write([]byte{byte(structs.AutopilotRequestType)}); err != nil { 280 return err 281 } 282 if err := encoder.Encode(config); err != nil { 283 return err 284 } 285 return nil 286 } 287 288 func (s *snapshot) persistConnectCA(sink raft.SnapshotSink, 289 encoder *codec.Encoder) error { 290 roots, err := s.state.CARoots() 291 if err != nil { 292 return err 293 } 294 295 for _, r := range roots { 296 if _, err := sink.Write([]byte{byte(structs.ConnectCARequestType)}); err != nil { 297 return err 298 } 299 if err := encoder.Encode(r); err != nil { 300 return err 301 } 302 } 303 304 return nil 305 } 306 307 func (s *snapshot) persistConnectCAConfig(sink raft.SnapshotSink, 308 encoder *codec.Encoder) error { 309 config, err := s.state.CAConfig() 310 if err != nil { 311 return err 312 } 313 // Make sure we don't write a nil config out to a snapshot. 314 if config == nil { 315 return nil 316 } 317 318 if _, err := sink.Write([]byte{byte(structs.ConnectCAConfigType)}); err != nil { 319 return err 320 } 321 if err := encoder.Encode(config); err != nil { 322 return err 323 } 324 return nil 325 } 326 327 func (s *snapshot) persistConnectCAProviderState(sink raft.SnapshotSink, 328 encoder *codec.Encoder) error { 329 state, err := s.state.CAProviderState() 330 if err != nil { 331 return err 332 } 333 334 for _, r := range state { 335 if _, err := sink.Write([]byte{byte(structs.ConnectCAProviderStateType)}); err != nil { 336 return err 337 } 338 if err := encoder.Encode(r); err != nil { 339 return err 340 } 341 } 342 return nil 343 } 344 345 func (s *snapshot) persistIntentions(sink raft.SnapshotSink, 346 encoder *codec.Encoder) error { 347 ixns, err := s.state.Intentions() 348 if err != nil { 349 return err 350 } 351 352 for _, ixn := range ixns { 353 if _, err := sink.Write([]byte{byte(structs.IntentionRequestType)}); err != nil { 354 return err 355 } 356 if err := encoder.Encode(ixn); err != nil { 357 return err 358 } 359 } 360 return nil 361 } 362 363 func (s *snapshot) persistIndex(sink raft.SnapshotSink, encoder *codec.Encoder) error { 364 // Get all the indexes 365 iter, err := s.state.Indexes() 366 if err != nil { 367 return err 368 } 369 370 for raw := iter.Next(); raw != nil; raw = iter.Next() { 371 // Prepare the request struct 372 idx := raw.(*state.IndexEntry) 373 374 // Write out a node registration 375 sink.Write([]byte{byte(structs.IndexRequestType)}) 376 if err := encoder.Encode(idx); err != nil { 377 return err 378 } 379 } 380 return nil 381 } 382 383 func restoreRegistration(header *snapshotHeader, restore *state.Restore, decoder *codec.Decoder) error { 384 var req structs.RegisterRequest 385 if err := decoder.Decode(&req); err != nil { 386 return err 387 } 388 if err := restore.Registration(header.LastIndex, &req); err != nil { 389 return err 390 } 391 return nil 392 } 393 394 func restoreKV(header *snapshotHeader, restore *state.Restore, decoder *codec.Decoder) error { 395 var req structs.DirEntry 396 if err := decoder.Decode(&req); err != nil { 397 return err 398 } 399 if err := restore.KVS(&req); err != nil { 400 return err 401 } 402 return nil 403 } 404 405 func restoreTombstone(header *snapshotHeader, restore *state.Restore, decoder *codec.Decoder) error { 406 var req structs.DirEntry 407 if err := decoder.Decode(&req); err != nil { 408 return err 409 } 410 411 // For historical reasons, these are serialized in the 412 // snapshots as KV entries. We want to keep the snapshot 413 // format compatible with pre-0.6 versions for now. 414 stone := &state.Tombstone{ 415 Key: req.Key, 416 Index: req.ModifyIndex, 417 } 418 if err := restore.Tombstone(stone); err != nil { 419 return err 420 } 421 return nil 422 } 423 424 func restoreSession(header *snapshotHeader, restore *state.Restore, decoder *codec.Decoder) error { 425 var req structs.Session 426 if err := decoder.Decode(&req); err != nil { 427 return err 428 } 429 if err := restore.Session(&req); err != nil { 430 return err 431 } 432 return nil 433 } 434 435 func restoreACL(header *snapshotHeader, restore *state.Restore, decoder *codec.Decoder) error { 436 var req structs.ACL 437 if err := decoder.Decode(&req); err != nil { 438 return err 439 } 440 441 if err := restore.ACLToken(req.Convert()); err != nil { 442 return err 443 } 444 return nil 445 } 446 447 // DEPRECATED (ACL-Legacy-Compat) - remove once v1 acl compat is removed 448 func restoreACLBootstrap(header *snapshotHeader, restore *state.Restore, decoder *codec.Decoder) error { 449 var req structs.ACLBootstrap 450 if err := decoder.Decode(&req); err != nil { 451 return err 452 } 453 454 // With V2 ACLs whether bootstrapping has been performed is stored in the index table like nomad 455 // so this "restores" into that index table. 456 return restore.IndexRestore(&state.IndexEntry{Key: "acl-token-bootstrap", Value: req.ModifyIndex}) 457 } 458 459 func restoreCoordinates(header *snapshotHeader, restore *state.Restore, decoder *codec.Decoder) error { 460 var req structs.Coordinates 461 if err := decoder.Decode(&req); err != nil { 462 return err 463 } 464 if err := restore.Coordinates(header.LastIndex, req); err != nil { 465 return err 466 } 467 return nil 468 } 469 470 func restorePreparedQuery(header *snapshotHeader, restore *state.Restore, decoder *codec.Decoder) error { 471 var req structs.PreparedQuery 472 if err := decoder.Decode(&req); err != nil { 473 return err 474 } 475 if err := restore.PreparedQuery(&req); err != nil { 476 return err 477 } 478 return nil 479 } 480 481 func restoreAutopilot(header *snapshotHeader, restore *state.Restore, decoder *codec.Decoder) error { 482 var req autopilot.Config 483 if err := decoder.Decode(&req); err != nil { 484 return err 485 } 486 if err := restore.Autopilot(&req); err != nil { 487 return err 488 } 489 return nil 490 } 491 492 func restoreIntention(header *snapshotHeader, restore *state.Restore, decoder *codec.Decoder) error { 493 var req structs.Intention 494 if err := decoder.Decode(&req); err != nil { 495 return err 496 } 497 if err := restore.Intention(&req); err != nil { 498 return err 499 } 500 return nil 501 } 502 503 func restoreConnectCA(header *snapshotHeader, restore *state.Restore, decoder *codec.Decoder) error { 504 var req structs.CARoot 505 if err := decoder.Decode(&req); err != nil { 506 return err 507 } 508 if err := restore.CARoot(&req); err != nil { 509 return err 510 } 511 return nil 512 } 513 514 func restoreConnectCAProviderState(header *snapshotHeader, restore *state.Restore, decoder *codec.Decoder) error { 515 var req structs.CAConsulProviderState 516 if err := decoder.Decode(&req); err != nil { 517 return err 518 } 519 if err := restore.CAProviderState(&req); err != nil { 520 return err 521 } 522 return nil 523 } 524 525 func restoreConnectCAConfig(header *snapshotHeader, restore *state.Restore, decoder *codec.Decoder) error { 526 var req structs.CAConfiguration 527 if err := decoder.Decode(&req); err != nil { 528 return err 529 } 530 if err := restore.CAConfig(&req); err != nil { 531 return err 532 } 533 return nil 534 } 535 536 func restoreIndex(header *snapshotHeader, restore *state.Restore, decoder *codec.Decoder) error { 537 var req state.IndexEntry 538 if err := decoder.Decode(&req); err != nil { 539 return err 540 } 541 return restore.IndexRestore(&req) 542 } 543 544 func restoreToken(header *snapshotHeader, restore *state.Restore, decoder *codec.Decoder) error { 545 var req structs.ACLToken 546 if err := decoder.Decode(&req); err != nil { 547 return err 548 } 549 550 // DEPRECATED (ACL-Legacy-Compat) 551 if req.Rules != "" { 552 // When we restore a snapshot we may have to correct old HCL in legacy 553 // tokens to prevent the in-memory representation from using an older 554 // syntax. 555 structs.SanitizeLegacyACLToken(&req) 556 } 557 558 return restore.ACLToken(&req) 559 } 560 561 func restorePolicy(header *snapshotHeader, restore *state.Restore, decoder *codec.Decoder) error { 562 var req structs.ACLPolicy 563 if err := decoder.Decode(&req); err != nil { 564 return err 565 } 566 return restore.ACLPolicy(&req) 567 }