Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1544)

Delta Between Two Patch Sets: environs/ec2/ec2.go

Issue 6408049: environs: turn environment configuration into a concrete type
Left Patch Set: Config 3000. Created 12 years, 8 months ago
Right Patch Set: environs: turn environment configuration into a concrete type Created 12 years, 8 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « environs/ec2/config_test.go ('k') | environs/ec2/export_test.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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
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
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
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 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b