github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/swarmkit/protobuf/plugin/storeobject/storeobject.go (about) 1 package storeobject 2 3 import ( 4 "strings" 5 6 "github.com/docker/swarmkit/protobuf/plugin" 7 "github.com/gogo/protobuf/proto" 8 "github.com/gogo/protobuf/protoc-gen-gogo/generator" 9 ) 10 11 // FIXME(aaronl): Look at fields inside the descriptor instead of 12 // special-casing based on name. 13 var typesWithNoSpec = map[string]struct{}{ 14 "Task": {}, 15 "Resource": {}, 16 "Extension": {}, 17 } 18 19 type storeObjectGen struct { 20 *generator.Generator 21 generator.PluginImports 22 eventsPkg generator.Single 23 stringsPkg generator.Single 24 } 25 26 func init() { 27 generator.RegisterPlugin(new(storeObjectGen)) 28 } 29 30 func (d *storeObjectGen) Name() string { 31 return "storeobject" 32 } 33 34 func (d *storeObjectGen) Init(g *generator.Generator) { 35 d.Generator = g 36 } 37 38 func (d *storeObjectGen) genMsgStoreObject(m *generator.Descriptor, storeObject *plugin.StoreObject) { 39 ccTypeName := generator.CamelCaseSlice(m.TypeName()) 40 41 // Generate event types 42 43 d.P("type ", ccTypeName, "CheckFunc func(t1, t2 *", ccTypeName, ") bool") 44 d.P() 45 46 // generate the event object type interface for this type 47 // event types implement some empty interfaces, for ease of use, like such: 48 // 49 // type EventCreate interface { 50 // IsEventCreatet() bool 51 // } 52 // 53 // type EventNode interface { 54 // IsEventNode() bool 55 // } 56 // 57 // then, each event has the corresponding interfaces implemented for its 58 // type. for example: 59 // 60 // func (e EventCreateNode) IsEventCreate() bool { 61 // return true 62 // } 63 // 64 // func (e EventCreateNode) IsEventNode() bool { 65 // return true 66 // } 67 // 68 // this lets the user filter events based on their interface type. 69 // note that the event type for each object type needs to be generated for 70 // each object. the event change type (Create/Update/Delete) is 71 // hand-written in the storeobject.go file because they are only needed 72 // once. 73 d.P("type Event", ccTypeName, " interface {") 74 d.In() 75 d.P("IsEvent", ccTypeName, "() bool") 76 d.Out() 77 d.P("}") 78 d.P() 79 80 for _, event := range []string{"Create", "Update", "Delete"} { 81 d.P("type Event", event, ccTypeName, " struct {") 82 d.In() 83 d.P(ccTypeName, " *", ccTypeName) 84 if event == "Update" { 85 d.P("Old", ccTypeName, " *", ccTypeName) 86 } 87 d.P("Checks []", ccTypeName, "CheckFunc") 88 d.Out() 89 d.P("}") 90 d.P() 91 d.P("func (e Event", event, ccTypeName, ") Matches(apiEvent ", d.eventsPkg.Use(), ".Event) bool {") 92 d.In() 93 d.P("typedEvent, ok := apiEvent.(Event", event, ccTypeName, ")") 94 d.P("if !ok {") 95 d.In() 96 d.P("return false") 97 d.Out() 98 d.P("}") 99 d.P() 100 d.P("for _, check := range e.Checks {") 101 d.In() 102 d.P("if !check(e.", ccTypeName, ", typedEvent.", ccTypeName, ") {") 103 d.In() 104 d.P("return false") 105 d.Out() 106 d.P("}") 107 d.Out() 108 d.P("}") 109 d.P("return true") 110 d.Out() 111 d.P("}") 112 d.P() 113 114 // implement event change type interface (IsEventCreate) 115 d.P("func (e Event", event, ccTypeName, ") IsEvent", event, "() bool {") 116 d.In() 117 d.P("return true") 118 d.Out() 119 d.P("}") 120 d.P() 121 122 // implement event object type interface (IsEventNode) 123 d.P("func (e Event", event, ccTypeName, ") IsEvent", ccTypeName, "() bool {") 124 d.In() 125 d.P("return true") 126 d.Out() 127 d.P("}") 128 d.P() 129 } 130 131 // Generate methods for this type 132 133 d.P("func (m *", ccTypeName, ") CopyStoreObject() StoreObject {") 134 d.In() 135 d.P("return m.Copy()") 136 d.Out() 137 d.P("}") 138 d.P() 139 140 d.P("func (m *", ccTypeName, ") GetMeta() Meta {") 141 d.In() 142 d.P("return m.Meta") 143 d.Out() 144 d.P("}") 145 d.P() 146 147 d.P("func (m *", ccTypeName, ") SetMeta(meta Meta) {") 148 d.In() 149 d.P("m.Meta = meta") 150 d.Out() 151 d.P("}") 152 d.P() 153 154 d.P("func (m *", ccTypeName, ") GetID() string {") 155 d.In() 156 d.P("return m.ID") 157 d.Out() 158 d.P("}") 159 d.P() 160 161 d.P("func (m *", ccTypeName, ") EventCreate() Event {") 162 d.In() 163 d.P("return EventCreate", ccTypeName, "{", ccTypeName, ": m}") 164 d.Out() 165 d.P("}") 166 d.P() 167 168 d.P("func (m *", ccTypeName, ") EventUpdate(oldObject StoreObject) Event {") 169 d.In() 170 d.P("if oldObject != nil {") 171 d.In() 172 d.P("return EventUpdate", ccTypeName, "{", ccTypeName, ": m, Old", ccTypeName, ": oldObject.(*", ccTypeName, ")}") 173 d.Out() 174 d.P("} else {") 175 d.In() 176 d.P("return EventUpdate", ccTypeName, "{", ccTypeName, ": m}") 177 d.Out() 178 d.P("}") 179 d.Out() 180 d.P("}") 181 d.P() 182 183 d.P("func (m *", ccTypeName, ") EventDelete() Event {") 184 d.In() 185 d.P("return EventDelete", ccTypeName, "{", ccTypeName, ": m}") 186 d.Out() 187 d.P("}") 188 d.P() 189 190 // Generate event check functions 191 192 if storeObject.WatchSelectors.ID != nil && *storeObject.WatchSelectors.ID { 193 d.P("func ", ccTypeName, "CheckID(v1, v2 *", ccTypeName, ") bool {") 194 d.In() 195 d.P("return v1.ID == v2.ID") 196 d.Out() 197 d.P("}") 198 d.P() 199 } 200 201 if storeObject.WatchSelectors.IDPrefix != nil && *storeObject.WatchSelectors.IDPrefix { 202 d.P("func ", ccTypeName, "CheckIDPrefix(v1, v2 *", ccTypeName, ") bool {") 203 d.In() 204 d.P("return ", d.stringsPkg.Use(), ".HasPrefix(v2.ID, v1.ID)") 205 d.Out() 206 d.P("}") 207 d.P() 208 } 209 210 if storeObject.WatchSelectors.Name != nil && *storeObject.WatchSelectors.Name { 211 d.P("func ", ccTypeName, "CheckName(v1, v2 *", ccTypeName, ") bool {") 212 d.In() 213 // Node is a special case 214 if *m.Name == "Node" { 215 d.P("if v1.Description == nil || v2.Description == nil {") 216 d.In() 217 d.P("return false") 218 d.Out() 219 d.P("}") 220 d.P("return v1.Description.Hostname == v2.Description.Hostname") 221 } else if _, hasNoSpec := typesWithNoSpec[*m.Name]; hasNoSpec { 222 d.P("return v1.Annotations.Name == v2.Annotations.Name") 223 } else { 224 d.P("return v1.Spec.Annotations.Name == v2.Spec.Annotations.Name") 225 } 226 d.Out() 227 d.P("}") 228 d.P() 229 } 230 231 if storeObject.WatchSelectors.NamePrefix != nil && *storeObject.WatchSelectors.NamePrefix { 232 d.P("func ", ccTypeName, "CheckNamePrefix(v1, v2 *", ccTypeName, ") bool {") 233 d.In() 234 // Node is a special case 235 if *m.Name == "Node" { 236 d.P("if v1.Description == nil || v2.Description == nil {") 237 d.In() 238 d.P("return false") 239 d.Out() 240 d.P("}") 241 d.P("return ", d.stringsPkg.Use(), ".HasPrefix(v2.Description.Hostname, v1.Description.Hostname)") 242 } else if _, hasNoSpec := typesWithNoSpec[*m.Name]; hasNoSpec { 243 d.P("return ", d.stringsPkg.Use(), ".HasPrefix(v2.Annotations.Name, v1.Annotations.Name)") 244 } else { 245 d.P("return ", d.stringsPkg.Use(), ".HasPrefix(v2.Spec.Annotations.Name, v1.Spec.Annotations.Name)") 246 } 247 d.Out() 248 d.P("}") 249 d.P() 250 } 251 252 if storeObject.WatchSelectors.Custom != nil && *storeObject.WatchSelectors.Custom { 253 d.P("func ", ccTypeName, "CheckCustom(v1, v2 *", ccTypeName, ") bool {") 254 d.In() 255 // Node is a special case 256 if _, hasNoSpec := typesWithNoSpec[*m.Name]; hasNoSpec { 257 d.P("return checkCustom(v1.Annotations, v2.Annotations)") 258 } else { 259 d.P("return checkCustom(v1.Spec.Annotations, v2.Spec.Annotations)") 260 } 261 d.Out() 262 d.P("}") 263 d.P() 264 } 265 266 if storeObject.WatchSelectors.CustomPrefix != nil && *storeObject.WatchSelectors.CustomPrefix { 267 d.P("func ", ccTypeName, "CheckCustomPrefix(v1, v2 *", ccTypeName, ") bool {") 268 d.In() 269 // Node is a special case 270 if _, hasNoSpec := typesWithNoSpec[*m.Name]; hasNoSpec { 271 d.P("return checkCustomPrefix(v1.Annotations, v2.Annotations)") 272 } else { 273 d.P("return checkCustomPrefix(v1.Spec.Annotations, v2.Spec.Annotations)") 274 } 275 d.Out() 276 d.P("}") 277 d.P() 278 } 279 280 if storeObject.WatchSelectors.NodeID != nil && *storeObject.WatchSelectors.NodeID { 281 d.P("func ", ccTypeName, "CheckNodeID(v1, v2 *", ccTypeName, ") bool {") 282 d.In() 283 d.P("return v1.NodeID == v2.NodeID") 284 d.Out() 285 d.P("}") 286 d.P() 287 } 288 289 if storeObject.WatchSelectors.ServiceID != nil && *storeObject.WatchSelectors.ServiceID { 290 d.P("func ", ccTypeName, "CheckServiceID(v1, v2 *", ccTypeName, ") bool {") 291 d.In() 292 d.P("return v1.ServiceID == v2.ServiceID") 293 d.Out() 294 d.P("}") 295 d.P() 296 } 297 298 if storeObject.WatchSelectors.Slot != nil && *storeObject.WatchSelectors.Slot { 299 d.P("func ", ccTypeName, "CheckSlot(v1, v2 *", ccTypeName, ") bool {") 300 d.In() 301 d.P("return v1.Slot == v2.Slot") 302 d.Out() 303 d.P("}") 304 d.P() 305 } 306 307 if storeObject.WatchSelectors.DesiredState != nil && *storeObject.WatchSelectors.DesiredState { 308 d.P("func ", ccTypeName, "CheckDesiredState(v1, v2 *", ccTypeName, ") bool {") 309 d.In() 310 d.P("return v1.DesiredState == v2.DesiredState") 311 d.Out() 312 d.P("}") 313 d.P() 314 } 315 316 if storeObject.WatchSelectors.Role != nil && *storeObject.WatchSelectors.Role { 317 d.P("func ", ccTypeName, "CheckRole(v1, v2 *", ccTypeName, ") bool {") 318 d.In() 319 d.P("return v1.Role == v2.Role") 320 d.Out() 321 d.P("}") 322 d.P() 323 } 324 325 if storeObject.WatchSelectors.Membership != nil && *storeObject.WatchSelectors.Membership { 326 d.P("func ", ccTypeName, "CheckMembership(v1, v2 *", ccTypeName, ") bool {") 327 d.In() 328 d.P("return v1.Spec.Membership == v2.Spec.Membership") 329 d.Out() 330 d.P("}") 331 d.P() 332 } 333 334 if storeObject.WatchSelectors.Kind != nil && *storeObject.WatchSelectors.Kind { 335 d.P("func ", ccTypeName, "CheckKind(v1, v2 *", ccTypeName, ") bool {") 336 d.In() 337 d.P("return v1.Kind == v2.Kind") 338 d.Out() 339 d.P("}") 340 d.P() 341 } 342 343 // Generate Convert*Watch function, for watch API. 344 if ccTypeName == "Resource" { 345 d.P("func ConvertResourceWatch(action WatchActionKind, filters []*SelectBy, kind string) ([]Event, error) {") 346 } else { 347 d.P("func Convert", ccTypeName, "Watch(action WatchActionKind, filters []*SelectBy) ([]Event, error) {") 348 } 349 d.In() 350 d.P("var (") 351 d.In() 352 d.P("m ", ccTypeName) 353 d.P("checkFuncs []", ccTypeName, "CheckFunc") 354 if storeObject.WatchSelectors.DesiredState != nil && *storeObject.WatchSelectors.DesiredState { 355 d.P("hasDesiredState bool") 356 } 357 if storeObject.WatchSelectors.Role != nil && *storeObject.WatchSelectors.Role { 358 d.P("hasRole bool") 359 } 360 if storeObject.WatchSelectors.Membership != nil && *storeObject.WatchSelectors.Membership { 361 d.P("hasMembership bool") 362 } 363 d.Out() 364 d.P(")") 365 if ccTypeName == "Resource" { 366 d.P("m.Kind = kind") 367 d.P("checkFuncs = append(checkFuncs, ResourceCheckKind)") 368 } 369 d.P() 370 d.P("for _, filter := range filters {") 371 d.In() 372 d.P("switch v := filter.By.(type) {") 373 374 if storeObject.WatchSelectors.ID != nil && *storeObject.WatchSelectors.ID { 375 d.P("case *SelectBy_ID:") 376 d.In() 377 d.P(`if m.ID != "" {`) 378 d.In() 379 d.P("return nil, errConflictingFilters") 380 d.Out() 381 d.P("}") 382 d.P("m.ID = v.ID") 383 d.P("checkFuncs = append(checkFuncs, ", ccTypeName, "CheckID)") 384 d.Out() 385 } 386 if storeObject.WatchSelectors.IDPrefix != nil && *storeObject.WatchSelectors.IDPrefix { 387 d.P("case *SelectBy_IDPrefix:") 388 d.In() 389 d.P(`if m.ID != "" {`) 390 d.In() 391 d.P("return nil, errConflictingFilters") 392 d.Out() 393 d.P("}") 394 d.P("m.ID = v.IDPrefix") 395 d.P("checkFuncs = append(checkFuncs, ", ccTypeName, "CheckIDPrefix)") 396 d.Out() 397 } 398 if storeObject.WatchSelectors.Name != nil && *storeObject.WatchSelectors.Name { 399 d.P("case *SelectBy_Name:") 400 d.In() 401 if *m.Name == "Node" { 402 d.P("if m.Description != nil {") 403 d.In() 404 d.P("return nil, errConflictingFilters") 405 d.Out() 406 d.P("}") 407 d.P("m.Description = &NodeDescription{Hostname: v.Name}") 408 409 } else if _, hasNoSpec := typesWithNoSpec[*m.Name]; hasNoSpec { 410 d.P(`if m.Annotations.Name != "" {`) 411 d.In() 412 d.P("return nil, errConflictingFilters") 413 d.Out() 414 d.P("}") 415 d.P("m.Annotations.Name = v.Name") 416 } else { 417 d.P(`if m.Spec.Annotations.Name != "" {`) 418 d.In() 419 d.P("return nil, errConflictingFilters") 420 d.Out() 421 d.P("}") 422 d.P("m.Spec.Annotations.Name = v.Name") 423 } 424 d.P("checkFuncs = append(checkFuncs, ", ccTypeName, "CheckName)") 425 d.Out() 426 } 427 if storeObject.WatchSelectors.NamePrefix != nil && *storeObject.WatchSelectors.NamePrefix { 428 d.P("case *SelectBy_NamePrefix:") 429 d.In() 430 if *m.Name == "Node" { 431 d.P("if m.Description != nil {") 432 d.In() 433 d.P("return nil, errConflictingFilters") 434 d.Out() 435 d.P("}") 436 d.P("m.Description = &NodeDescription{Hostname: v.NamePrefix}") 437 438 } else if _, hasNoSpec := typesWithNoSpec[*m.Name]; hasNoSpec { 439 d.P(`if m.Annotations.Name != "" {`) 440 d.In() 441 d.P("return nil, errConflictingFilters") 442 d.Out() 443 d.P("}") 444 d.P("m.Annotations.Name = v.NamePrefix") 445 } else { 446 d.P(`if m.Spec.Annotations.Name != "" {`) 447 d.In() 448 d.P("return nil, errConflictingFilters") 449 d.Out() 450 d.P("}") 451 d.P("m.Spec.Annotations.Name = v.NamePrefix") 452 } 453 d.P("checkFuncs = append(checkFuncs, ", ccTypeName, "CheckNamePrefix)") 454 d.Out() 455 } 456 if storeObject.WatchSelectors.Custom != nil && *storeObject.WatchSelectors.Custom { 457 d.P("case *SelectBy_Custom:") 458 d.In() 459 if _, hasNoSpec := typesWithNoSpec[*m.Name]; hasNoSpec { 460 d.P(`if len(m.Annotations.Indices) != 0 {`) 461 d.In() 462 d.P("return nil, errConflictingFilters") 463 d.Out() 464 d.P("}") 465 d.P("m.Annotations.Indices = []IndexEntry{{Key: v.Custom.Index, Val: v.Custom.Value}}") 466 } else { 467 d.P(`if len(m.Spec.Annotations.Indices) != 0 {`) 468 d.In() 469 d.P("return nil, errConflictingFilters") 470 d.Out() 471 d.P("}") 472 d.P("m.Spec.Annotations.Indices = []IndexEntry{{Key: v.Custom.Index, Val: v.Custom.Value}}") 473 } 474 d.P("checkFuncs = append(checkFuncs, ", ccTypeName, "CheckCustom)") 475 d.Out() 476 } 477 if storeObject.WatchSelectors.CustomPrefix != nil && *storeObject.WatchSelectors.CustomPrefix { 478 d.P("case *SelectBy_CustomPrefix:") 479 d.In() 480 if _, hasNoSpec := typesWithNoSpec[*m.Name]; hasNoSpec { 481 d.P(`if len(m.Annotations.Indices) != 0 {`) 482 d.In() 483 d.P("return nil, errConflictingFilters") 484 d.Out() 485 d.P("}") 486 d.P("m.Annotations.Indices = []IndexEntry{{Key: v.CustomPrefix.Index, Val: v.CustomPrefix.Value}}") 487 } else { 488 d.P(`if len(m.Spec.Annotations.Indices) != 0 {`) 489 d.In() 490 d.P("return nil, errConflictingFilters") 491 d.Out() 492 d.P("}") 493 d.P("m.Spec.Annotations.Indices = []IndexEntry{{Key: v.CustomPrefix.Index, Val: v.CustomPrefix.Value}}") 494 } 495 d.P("checkFuncs = append(checkFuncs, ", ccTypeName, "CheckCustomPrefix)") 496 d.Out() 497 } 498 if storeObject.WatchSelectors.ServiceID != nil && *storeObject.WatchSelectors.ServiceID { 499 d.P("case *SelectBy_ServiceID:") 500 d.In() 501 d.P(`if m.ServiceID != "" {`) 502 d.In() 503 d.P("return nil, errConflictingFilters") 504 d.Out() 505 d.P("}") 506 d.P("m.ServiceID = v.ServiceID") 507 d.P("checkFuncs = append(checkFuncs, ", ccTypeName, "CheckServiceID)") 508 d.Out() 509 } 510 if storeObject.WatchSelectors.NodeID != nil && *storeObject.WatchSelectors.NodeID { 511 d.P("case *SelectBy_NodeID:") 512 d.In() 513 d.P(`if m.NodeID != "" {`) 514 d.In() 515 d.P("return nil, errConflictingFilters") 516 d.Out() 517 d.P("}") 518 d.P("m.NodeID = v.NodeID") 519 d.P("checkFuncs = append(checkFuncs, ", ccTypeName, "CheckNodeID)") 520 d.Out() 521 } 522 if storeObject.WatchSelectors.Slot != nil && *storeObject.WatchSelectors.Slot { 523 d.P("case *SelectBy_Slot:") 524 d.In() 525 d.P(`if m.Slot != 0 || m.ServiceID != "" {`) 526 d.In() 527 d.P("return nil, errConflictingFilters") 528 d.Out() 529 d.P("}") 530 d.P("m.ServiceID = v.Slot.ServiceID") 531 d.P("m.Slot = v.Slot.Slot") 532 d.P("checkFuncs = append(checkFuncs, ", ccTypeName, "CheckNodeID, ", ccTypeName, "CheckSlot)") 533 d.Out() 534 } 535 if storeObject.WatchSelectors.DesiredState != nil && *storeObject.WatchSelectors.DesiredState { 536 d.P("case *SelectBy_DesiredState:") 537 d.In() 538 d.P(`if hasDesiredState {`) 539 d.In() 540 d.P("return nil, errConflictingFilters") 541 d.Out() 542 d.P("}") 543 d.P("hasDesiredState = true") 544 d.P("m.DesiredState = v.DesiredState") 545 d.P("checkFuncs = append(checkFuncs, ", ccTypeName, "CheckDesiredState)") 546 d.Out() 547 } 548 if storeObject.WatchSelectors.Role != nil && *storeObject.WatchSelectors.Role { 549 d.P("case *SelectBy_Role:") 550 d.In() 551 d.P(`if hasRole {`) 552 d.In() 553 d.P("return nil, errConflictingFilters") 554 d.Out() 555 d.P("}") 556 d.P("hasRole = true") 557 d.P("m.Role = v.Role") 558 d.P("checkFuncs = append(checkFuncs, ", ccTypeName, "CheckRole)") 559 d.Out() 560 } 561 if storeObject.WatchSelectors.Membership != nil && *storeObject.WatchSelectors.Membership { 562 d.P("case *SelectBy_Membership:") 563 d.In() 564 d.P(`if hasMembership {`) 565 d.In() 566 d.P("return nil, errConflictingFilters") 567 d.Out() 568 d.P("}") 569 d.P("hasMembership = true") 570 d.P("m.Spec.Membership = v.Membership") 571 d.P("checkFuncs = append(checkFuncs, ", ccTypeName, "CheckMembership)") 572 d.Out() 573 } 574 575 d.P("}") 576 d.Out() 577 d.P("}") 578 d.P("var events []Event") 579 d.P("if (action & WatchActionKindCreate) != 0 {") 580 d.In() 581 d.P("events = append(events, EventCreate", ccTypeName, "{", ccTypeName, ": &m, Checks: checkFuncs})") 582 d.Out() 583 d.P("}") 584 d.P("if (action & WatchActionKindUpdate) != 0 {") 585 d.In() 586 d.P("events = append(events, EventUpdate", ccTypeName, "{", ccTypeName, ": &m, Checks: checkFuncs})") 587 d.Out() 588 d.P("}") 589 d.P("if (action & WatchActionKindRemove) != 0 {") 590 d.In() 591 d.P("events = append(events, EventDelete", ccTypeName, "{", ccTypeName, ": &m, Checks: checkFuncs})") 592 d.Out() 593 d.P("}") 594 d.P("if len(events) == 0 {") 595 d.In() 596 d.P("return nil, errUnrecognizedAction") 597 d.Out() 598 d.P("}") 599 d.P("return events, nil") 600 d.Out() 601 d.P("}") 602 d.P() 603 604 /* switch v := filter.By.(type) { 605 default: 606 return nil, status.Errorf(codes.InvalidArgument, "selector type %T is unsupported for tasks", filter.By) 607 } 608 */ 609 610 // Generate indexer by ID 611 612 d.P("type ", ccTypeName, "IndexerByID struct{}") 613 d.P() 614 615 d.genFromArgs(ccTypeName + "IndexerByID") 616 d.genPrefixFromArgs(ccTypeName + "IndexerByID") 617 618 d.P("func (indexer ", ccTypeName, "IndexerByID) FromObject(obj interface{}) (bool, []byte, error) {") 619 d.In() 620 d.P("m := obj.(*", ccTypeName, ")") 621 // Add the null character as a terminator 622 d.P(`return true, []byte(m.ID + "\x00"), nil`) 623 d.Out() 624 d.P("}") 625 626 // Generate indexer by name 627 628 d.P("type ", ccTypeName, "IndexerByName struct{}") 629 d.P() 630 631 d.genFromArgs(ccTypeName + "IndexerByName") 632 d.genPrefixFromArgs(ccTypeName + "IndexerByName") 633 634 d.P("func (indexer ", ccTypeName, "IndexerByName) FromObject(obj interface{}) (bool, []byte, error) {") 635 d.In() 636 d.P("m := obj.(*", ccTypeName, ")") 637 if _, hasNoSpec := typesWithNoSpec[*m.Name]; hasNoSpec { 638 d.P(`val := m.Annotations.Name`) 639 } else { 640 d.P(`val := m.Spec.Annotations.Name`) 641 } 642 // Add the null character as a terminator 643 d.P("return true, []byte(", d.stringsPkg.Use(), `.ToLower(val) + "\x00"), nil`) 644 d.Out() 645 d.P("}") 646 647 // Generate custom indexer 648 649 d.P("type ", ccTypeName, "CustomIndexer struct{}") 650 d.P() 651 652 d.genFromArgs(ccTypeName + "CustomIndexer") 653 d.genPrefixFromArgs(ccTypeName + "CustomIndexer") 654 655 d.P("func (indexer ", ccTypeName, "CustomIndexer) FromObject(obj interface{}) (bool, [][]byte, error) {") 656 d.In() 657 d.P("m := obj.(*", ccTypeName, ")") 658 if _, hasNoSpec := typesWithNoSpec[*m.Name]; hasNoSpec { 659 d.P(`return customIndexer("", &m.Annotations)`) 660 } else { 661 d.P(`return customIndexer("", &m.Spec.Annotations)`) 662 } 663 d.Out() 664 d.P("}") 665 } 666 667 func (d *storeObjectGen) genFromArgs(indexerName string) { 668 d.P("func (indexer ", indexerName, ") FromArgs(args ...interface{}) ([]byte, error) {") 669 d.In() 670 d.P("return fromArgs(args...)") 671 d.Out() 672 d.P("}") 673 } 674 675 func (d *storeObjectGen) genPrefixFromArgs(indexerName string) { 676 d.P("func (indexer ", indexerName, ") PrefixFromArgs(args ...interface{}) ([]byte, error) {") 677 d.In() 678 d.P("return prefixFromArgs(args...)") 679 d.Out() 680 d.P("}") 681 682 } 683 684 func (d *storeObjectGen) genNewStoreAction(topLevelObjs []string) { 685 // Generate NewStoreAction 686 d.P("func NewStoreAction(c Event) (StoreAction, error) {") 687 d.In() 688 d.P("var sa StoreAction") 689 d.P("switch v := c.(type) {") 690 for _, ccTypeName := range topLevelObjs { 691 d.P("case EventCreate", ccTypeName, ":") 692 d.In() 693 d.P("sa.Action = StoreActionKindCreate") 694 d.P("sa.Target = &StoreAction_", ccTypeName, "{", ccTypeName, ": v.", ccTypeName, "}") 695 d.Out() 696 d.P("case EventUpdate", ccTypeName, ":") 697 d.In() 698 d.P("sa.Action = StoreActionKindUpdate") 699 d.P("sa.Target = &StoreAction_", ccTypeName, "{", ccTypeName, ": v.", ccTypeName, "}") 700 d.Out() 701 d.P("case EventDelete", ccTypeName, ":") 702 d.In() 703 d.P("sa.Action = StoreActionKindRemove") 704 d.P("sa.Target = &StoreAction_", ccTypeName, "{", ccTypeName, ": v.", ccTypeName, "}") 705 d.Out() 706 } 707 d.P("default:") 708 d.In() 709 d.P("return StoreAction{}, errUnknownStoreAction") 710 d.Out() 711 d.P("}") 712 d.P("return sa, nil") 713 d.Out() 714 d.P("}") 715 d.P() 716 } 717 718 func (d *storeObjectGen) genWatchMessageEvent(topLevelObjs []string) { 719 // Generate WatchMessageEvent 720 d.P("func WatchMessageEvent(c Event) *WatchMessage_Event {") 721 d.In() 722 d.P("switch v := c.(type) {") 723 for _, ccTypeName := range topLevelObjs { 724 d.P("case EventCreate", ccTypeName, ":") 725 d.In() 726 d.P("return &WatchMessage_Event{Action: WatchActionKindCreate, Object: &Object{Object: &Object_", ccTypeName, "{", ccTypeName, ": v.", ccTypeName, "}}}") 727 d.Out() 728 d.P("case EventUpdate", ccTypeName, ":") 729 d.In() 730 d.P("if v.Old", ccTypeName, " != nil {") 731 d.In() 732 d.P("return &WatchMessage_Event{Action: WatchActionKindUpdate, Object: &Object{Object: &Object_", ccTypeName, "{", ccTypeName, ": v.", ccTypeName, "}}, OldObject: &Object{Object: &Object_", ccTypeName, "{", ccTypeName, ": v.Old", ccTypeName, "}}}") 733 d.Out() 734 d.P("} else {") 735 d.In() 736 d.P("return &WatchMessage_Event{Action: WatchActionKindUpdate, Object: &Object{Object: &Object_", ccTypeName, "{", ccTypeName, ": v.", ccTypeName, "}}}") 737 d.Out() 738 d.P("}") 739 d.Out() 740 d.P("case EventDelete", ccTypeName, ":") 741 d.In() 742 d.P("return &WatchMessage_Event{Action: WatchActionKindRemove, Object: &Object{Object: &Object_", ccTypeName, "{", ccTypeName, ": v.", ccTypeName, "}}}") 743 d.Out() 744 } 745 d.P("}") 746 d.P("return nil") 747 d.Out() 748 d.P("}") 749 d.P() 750 } 751 752 func (d *storeObjectGen) genEventFromStoreAction(topLevelObjs []string) { 753 // Generate EventFromStoreAction 754 d.P("func EventFromStoreAction(sa StoreAction, oldObject StoreObject) (Event, error) {") 755 d.In() 756 d.P("switch v := sa.Target.(type) {") 757 for _, ccTypeName := range topLevelObjs { 758 d.P("case *StoreAction_", ccTypeName, ":") 759 d.In() 760 d.P("switch sa.Action {") 761 762 d.P("case StoreActionKindCreate:") 763 d.In() 764 d.P("return EventCreate", ccTypeName, "{", ccTypeName, ": v.", ccTypeName, "}, nil") 765 d.Out() 766 767 d.P("case StoreActionKindUpdate:") 768 d.In() 769 d.P("if oldObject != nil {") 770 d.In() 771 d.P("return EventUpdate", ccTypeName, "{", ccTypeName, ": v.", ccTypeName, ", Old", ccTypeName, ": oldObject.(*", ccTypeName, ")}, nil") 772 d.Out() 773 d.P("} else {") 774 d.In() 775 d.P("return EventUpdate", ccTypeName, "{", ccTypeName, ": v.", ccTypeName, "}, nil") 776 d.Out() 777 d.P("}") 778 d.Out() 779 780 d.P("case StoreActionKindRemove:") 781 d.In() 782 d.P("return EventDelete", ccTypeName, "{", ccTypeName, ": v.", ccTypeName, "}, nil") 783 d.Out() 784 785 d.P("}") 786 d.Out() 787 } 788 d.P("}") 789 d.P("return nil, errUnknownStoreAction") 790 d.Out() 791 d.P("}") 792 d.P() 793 } 794 795 func (d *storeObjectGen) genConvertWatchArgs(topLevelObjs []string) { 796 // Generate ConvertWatchArgs 797 d.P("func ConvertWatchArgs(entries []*WatchRequest_WatchEntry) ([]Event, error) {") 798 d.In() 799 d.P("var events []Event") 800 d.P("for _, entry := range entries {") 801 d.In() 802 d.P("var newEvents []Event") 803 d.P("var err error") 804 d.P("switch entry.Kind {") 805 d.P(`case "":`) 806 d.In() 807 d.P("return nil, errNoKindSpecified") 808 d.Out() 809 for _, ccTypeName := range topLevelObjs { 810 if ccTypeName == "Resource" { 811 d.P("default:") 812 d.In() 813 d.P("newEvents, err = ConvertResourceWatch(entry.Action, entry.Filters, entry.Kind)") 814 d.Out() 815 } else { 816 d.P(`case "`, strings.ToLower(ccTypeName), `":`) 817 d.In() 818 d.P("newEvents, err = Convert", ccTypeName, "Watch(entry.Action, entry.Filters)") 819 d.Out() 820 } 821 } 822 d.P("}") 823 d.P("if err != nil {") 824 d.In() 825 d.P("return nil, err") 826 d.Out() 827 d.P("}") 828 d.P("events = append(events, newEvents...)") 829 830 d.Out() 831 d.P("}") 832 d.P("return events, nil") 833 d.Out() 834 d.P("}") 835 d.P() 836 } 837 838 func (d *storeObjectGen) Generate(file *generator.FileDescriptor) { 839 d.PluginImports = generator.NewPluginImports(d.Generator) 840 d.eventsPkg = d.NewImport("github.com/docker/go-events") 841 d.stringsPkg = d.NewImport("strings") 842 843 var topLevelObjs []string 844 845 for _, m := range file.Messages() { 846 if m.DescriptorProto.GetOptions().GetMapEntry() { 847 continue 848 } 849 850 if m.Options == nil { 851 continue 852 } 853 storeObjIntf, err := proto.GetExtension(m.Options, plugin.E_StoreObject) 854 if err != nil { 855 // no StoreObject extension 856 continue 857 } 858 859 d.genMsgStoreObject(m, storeObjIntf.(*plugin.StoreObject)) 860 861 topLevelObjs = append(topLevelObjs, generator.CamelCaseSlice(m.TypeName())) 862 } 863 864 if len(topLevelObjs) != 0 { 865 d.genNewStoreAction(topLevelObjs) 866 d.genEventFromStoreAction(topLevelObjs) 867 868 // for watch API 869 d.genWatchMessageEvent(topLevelObjs) 870 d.genConvertWatchArgs(topLevelObjs) 871 } 872 }