LEFT | RIGHT |
1 package ec2 | 1 package ec2 |
2 | 2 |
3 import ( | 3 import ( |
4 "fmt" | 4 "fmt" |
5 "launchpad.net/goamz/aws" | 5 "launchpad.net/goamz/aws" |
6 "launchpad.net/goamz/ec2" | 6 "launchpad.net/goamz/ec2" |
7 "launchpad.net/goamz/s3" | 7 "launchpad.net/goamz/s3" |
8 "launchpad.net/juju-core/environs" | 8 "launchpad.net/juju-core/environs" |
9 "launchpad.net/juju-core/environs/config" | 9 "launchpad.net/juju-core/environs/config" |
10 "launchpad.net/juju-core/log" | 10 "launchpad.net/juju-core/log" |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 func (inst *instance) WaitDNSName() (string, error) { | 91 func (inst *instance) WaitDNSName() (string, error) { |
92 for a := longAttempt.Start(); a.Next(); { | 92 for a := longAttempt.Start(); a.Next(); { |
93 name, err := inst.DNSName() | 93 name, err := inst.DNSName() |
94 if err == nil || err != environs.ErrNoDNSName { | 94 if err == nil || err != environs.ErrNoDNSName { |
95 return name, err | 95 return name, err |
96 } | 96 } |
97 } | 97 } |
98 return "", fmt.Errorf("timed out trying to get DNS address for %v", inst
.Id()) | 98 return "", fmt.Errorf("timed out trying to get DNS address for %v", inst
.Id()) |
99 } | 99 } |
100 | 100 |
101 func (inst *instance) OpenPorts(machineId int, ports []state.Port) error { | |
102 return fmt.Errorf("ec2 OpenPorts not implemented") | |
103 } | |
104 | |
105 func (inst *instance) ClosePorts(machineId int, ports []state.Port) error { | |
106 return fmt.Errorf("ec2 ClosePorts not implemented") | |
107 } | |
108 | |
109 func (inst *instance) Ports(machineId int) (ports []state.Port, err error) { | |
110 return nil, fmt.Errorf("ec2 Ports not implemented") | |
111 } | |
112 | |
113 func (p environProvider) Open(cfg *config.Config) (environs.Environ, error) { | 101 func (p environProvider) Open(cfg *config.Config) (environs.Environ, error) { |
114 log.Printf("environs/ec2: opening environment %q", cfg.Name()) | 102 log.Printf("environs/ec2: opening environment %q", cfg.Name()) |
115 e := new(environ) | 103 e := new(environ) |
116 » e.SetConfig(cfg) | 104 » err := e.SetConfig(cfg) |
| 105 » if err != nil { |
| 106 » » return nil, err |
| 107 » } |
117 return e, nil | 108 return e, nil |
118 } | 109 } |
119 | 110 |
120 func (e *environ) SetConfig(cfg *config.Config) error { | 111 func (e *environ) SetConfig(cfg *config.Config) error { |
121 config, err := newConfig(cfg) | 112 config, err := newConfig(cfg) |
122 if err != nil { | 113 if err != nil { |
123 return err | 114 return err |
124 } | 115 } |
125 if aws.Regions[config.region].EC2Endpoint == "" { | 116 if aws.Regions[config.region].EC2Endpoint == "" { |
126 » » return fmt.Errorf("no ec2 endpoint found for region %q, opening
%q", config.region, config.name) | 117 » » return fmt.Errorf("environment %q references unknown EC2 region
%q", config.name, config.region) |
127 } | 118 } |
128 e.configMutex.Lock() | 119 e.configMutex.Lock() |
129 defer e.configMutex.Unlock() | 120 defer e.configMutex.Unlock() |
130 // TODO(dfc) bug #1018207, renaming an environment once it is in use sho
uld be forbidden | 121 // TODO(dfc) bug #1018207, renaming an environment once it is in use sho
uld be forbidden |
131 e.name = config.name | 122 e.name = config.name |
132 e.configUnlocked = config | 123 e.configUnlocked = config |
133 e.ec2Unlocked = ec2.New(config.auth, aws.Regions[config.region]) | 124 e.ec2Unlocked = ec2.New(config.auth, aws.Regions[config.region]) |
134 e.s3Unlocked = s3.New(config.auth, aws.Regions[config.region]) | 125 e.s3Unlocked = s3.New(config.auth, aws.Regions[config.region]) |
135 | 126 |
136 // create new storage instances, existing instances continue | 127 // create new storage instances, existing instances continue |
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
509 } | 500 } |
510 return firstErr | 501 return firstErr |
511 } | 502 } |
512 | 503 |
513 func (e *environ) machineGroupName(machineId int) string { | 504 func (e *environ) machineGroupName(machineId int) string { |
514 return fmt.Sprintf("%s-%d", e.groupName(), machineId) | 505 return fmt.Sprintf("%s-%d", e.groupName(), machineId) |
515 } | 506 } |
516 | 507 |
517 func (e *environ) groupName() string { | 508 func (e *environ) groupName() string { |
518 return "juju-" + e.name | 509 return "juju-" + e.name |
| 510 } |
| 511 |
| 512 func (inst *instance) OpenPorts(machineId int, ports []state.Port) error { |
| 513 if len(ports) == 0 { |
| 514 return nil |
| 515 } |
| 516 // Give permissions for anyone to access the given ports. |
| 517 ipPerms := portsToIPPerms(ports) |
| 518 g := ec2.SecurityGroup{Name: inst.e.machineGroupName(machineId)} |
| 519 _, err := inst.e.ec2().AuthorizeSecurityGroup(g, ipPerms) |
| 520 if err != nil && ec2ErrCode(err) == "InvalidPermission.Duplicate" { |
| 521 if len(ports) == 1 { |
| 522 return nil |
| 523 } |
| 524 // If there's more than one port and we get a duplicate error, |
| 525 // then we go through authorizing each port individually, |
| 526 // otherwise the ports that were *not* duplicates will have |
| 527 // been ignored |
| 528 for i := range ipPerms { |
| 529 _, err := inst.e.ec2().AuthorizeSecurityGroup(g, ipPerms
[i:i+1]) |
| 530 if err != nil && ec2ErrCode(err) != "InvalidPermission.D
uplicate" { |
| 531 return fmt.Errorf("cannot open port %v: %v", ipP
erms[i], err) |
| 532 } |
| 533 } |
| 534 return nil |
| 535 } |
| 536 if err != nil { |
| 537 return fmt.Errorf("cannot open ports: %v", err) |
| 538 } |
| 539 return nil |
| 540 } |
| 541 |
| 542 func (inst *instance) ClosePorts(machineId int, ports []state.Port) error { |
| 543 if len(ports) == 0 { |
| 544 return nil |
| 545 } |
| 546 // Revoke permissions for anyone to access the given ports. |
| 547 // Note that ec2 allows the revocation of permissions that aren't |
| 548 // granted, so this is naturally idempotent. |
| 549 g := ec2.SecurityGroup{Name: inst.e.machineGroupName(machineId)} |
| 550 _, err := inst.e.ec2().RevokeSecurityGroup(g, portsToIPPerms(ports)) |
| 551 if err != nil { |
| 552 return fmt.Errorf("cannot close ports: %v", err) |
| 553 } |
| 554 return nil |
| 555 } |
| 556 |
| 557 func portsToIPPerms(ports []state.Port) []ec2.IPPerm { |
| 558 ipPerms := make([]ec2.IPPerm, len(ports)) |
| 559 for i, p := range ports { |
| 560 ipPerms[i] = ec2.IPPerm{ |
| 561 Protocol: p.Protocol, |
| 562 FromPort: p.Number, |
| 563 ToPort: p.Number, |
| 564 SourceIPs: []string{"0.0.0.0/0"}, |
| 565 } |
| 566 } |
| 567 return ipPerms |
| 568 } |
| 569 |
| 570 func (inst *instance) Ports(machineId int) (ports []state.Port, err error) { |
| 571 g := ec2.SecurityGroup{Name: inst.e.machineGroupName(machineId)} |
| 572 resp, err := inst.e.ec2().SecurityGroups([]ec2.SecurityGroup{g}, nil) |
| 573 if err != nil { |
| 574 return nil, err |
| 575 } |
| 576 if len(resp.Groups) != 1 { |
| 577 return nil, fmt.Errorf("expected one security group, got %d", le
n(resp.Groups)) |
| 578 } |
| 579 for _, p := range resp.Groups[0].IPPerms { |
| 580 if len(p.SourceIPs) != 1 { |
| 581 log.Printf("environs/ec2: unexpected IP permission found
: %v", p) |
| 582 continue |
| 583 } |
| 584 for i := p.FromPort; i <= p.ToPort; i++ { |
| 585 ports = append(ports, state.Port{ |
| 586 Protocol: p.Protocol, |
| 587 Number: i, |
| 588 }) |
| 589 } |
| 590 } |
| 591 state.SortPorts(ports) |
| 592 return ports, nil |
519 } | 593 } |
520 | 594 |
521 // setUpGroups creates the security groups for the new machine, and | 595 // setUpGroups creates the security groups for the new machine, and |
522 // returns them. | 596 // returns them. |
523 //· | 597 //· |
524 // Instances are tagged with a group so they can be distinguished from | 598 // Instances are tagged with a group so they can be distinguished from |
525 // other instances that might be running on the same EC2 account. In | 599 // other instances that might be running on the same EC2 account. In |
526 // addition, a specific machine security group is created for each | 600 // addition, a specific machine security group is created for each |
527 // machine, so that its firewall rules can be configured per machine. | 601 // machine, so that its firewall rules can be configured per machine. |
528 func (e *environ) setUpGroups(machineId int) ([]ec2.SecurityGroup, error) { | 602 func (e *environ) setUpGroups(machineId int) ([]ec2.SecurityGroup, error) { |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
663 | 737 |
664 // If the err is of type *ec2.Error, ec2ErrCode returns | 738 // If the err is of type *ec2.Error, ec2ErrCode returns |
665 // its code, otherwise it returns the empty string. | 739 // its code, otherwise it returns the empty string. |
666 func ec2ErrCode(err error) string { | 740 func ec2ErrCode(err error) string { |
667 ec2err, _ := err.(*ec2.Error) | 741 ec2err, _ := err.(*ec2.Error) |
668 if ec2err == nil { | 742 if ec2err == nil { |
669 return "" | 743 return "" |
670 } | 744 } |
671 return ec2err.Code | 745 return ec2err.Code |
672 } | 746 } |
LEFT | RIGHT |