/
instance.go
127 lines (110 loc) · 3.31 KB
/
instance.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// Copyright 2011-2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.
package ec2
import (
"fmt"
"sync"
"gopkg.in/amz.v3/ec2"
"github.com/juju/juju/environs/config"
"github.com/juju/juju/instance"
"github.com/juju/juju/network"
)
type ec2Instance struct {
e *environ
mu sync.Mutex
*ec2.Instance
}
func (inst *ec2Instance) String() string {
return string(inst.Id())
}
var _ instance.Instance = (*ec2Instance)(nil)
func (inst *ec2Instance) getInstance() *ec2.Instance {
inst.mu.Lock()
defer inst.mu.Unlock()
return inst.Instance
}
func (inst *ec2Instance) Id() instance.Id {
return instance.Id(inst.getInstance().InstanceId)
}
func (inst *ec2Instance) Status() string {
return inst.getInstance().State.Name
}
// Refresh implements instance.Refresh(), requerying the
// Instance details over the ec2 api
func (inst *ec2Instance) Refresh() error {
_, err := inst.refresh()
return err
}
// refresh requeries Instance details over the ec2 api.
func (inst *ec2Instance) refresh() (*ec2.Instance, error) {
id := inst.Id()
insts, err := inst.e.Instances([]instance.Id{id})
if err != nil {
return nil, err
}
inst.mu.Lock()
defer inst.mu.Unlock()
inst.Instance = insts[0].(*ec2Instance).Instance
return inst.Instance, nil
}
// Addresses implements network.Addresses() returning generic address
// details for the instance, and requerying the ec2 api if required.
func (inst *ec2Instance) Addresses() ([]network.Address, error) {
// TODO(gz): Stop relying on this requerying logic, maybe remove error
instInstance := inst.getInstance()
var addresses []network.Address
possibleAddresses := []network.Address{
{
Value: instInstance.IPAddress,
Type: network.IPv4Address,
Scope: network.ScopePublic,
},
{
Value: instInstance.PrivateIPAddress,
Type: network.IPv4Address,
Scope: network.ScopeCloudLocal,
},
}
for _, address := range possibleAddresses {
if address.Value != "" {
addresses = append(addresses, address)
}
}
return addresses, nil
}
func (inst *ec2Instance) OpenPorts(machineId string, ports []network.PortRange) error {
if inst.e.Config().FirewallMode() != config.FwInstance {
return fmt.Errorf("invalid firewall mode %q for opening ports on instance",
inst.e.Config().FirewallMode())
}
name := inst.e.machineGroupName(machineId)
if err := inst.e.openPortsInGroup(name, ports); err != nil {
return err
}
logger.Infof("opened ports in security group %s: %v", name, ports)
return nil
}
func (inst *ec2Instance) ClosePorts(machineId string, ports []network.PortRange) error {
if inst.e.Config().FirewallMode() != config.FwInstance {
return fmt.Errorf("invalid firewall mode %q for closing ports on instance",
inst.e.Config().FirewallMode())
}
name := inst.e.machineGroupName(machineId)
if err := inst.e.closePortsInGroup(name, ports); err != nil {
return err
}
logger.Infof("closed ports in security group %s: %v", name, ports)
return nil
}
func (inst *ec2Instance) Ports(machineId string) ([]network.PortRange, error) {
if inst.e.Config().FirewallMode() != config.FwInstance {
return nil, fmt.Errorf("invalid firewall mode %q for retrieving ports from instance",
inst.e.Config().FirewallMode())
}
name := inst.e.machineGroupName(machineId)
ranges, err := inst.e.portsInGroup(name)
if err != nil {
return nil, err
}
return ranges, nil
}