github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/api/firewaller/firewaller.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package firewaller 5 6 import ( 7 "github.com/juju/errors" 8 "gopkg.in/juju/names.v2" 9 10 "github.com/juju/juju/api" 11 "github.com/juju/juju/api/base" 12 "github.com/juju/juju/api/common" 13 "github.com/juju/juju/api/common/cloudspec" 14 apiwatcher "github.com/juju/juju/api/watcher" 15 "github.com/juju/juju/apiserver/params" 16 "github.com/juju/juju/core/relation" 17 "github.com/juju/juju/core/watcher" 18 "gopkg.in/macaroon.v2-unstable" 19 ) 20 21 const firewallerFacade = "Firewaller" 22 23 // Client provides access to the Firewaller API facade. 24 type Client struct { 25 facade base.FacadeCaller 26 *common.ModelWatcher 27 *cloudspec.CloudSpecAPI 28 } 29 30 // NewClient creates a new client-side Firewaller API facade. 31 func NewClient(caller base.APICaller) (*Client, error) { 32 modelTag, isModel := caller.ModelTag() 33 if !isModel { 34 return nil, errors.New("expected model specific API connection") 35 } 36 facadeCaller := base.NewFacadeCaller(caller, firewallerFacade) 37 return &Client{ 38 facade: facadeCaller, 39 ModelWatcher: common.NewModelWatcher(facadeCaller), 40 CloudSpecAPI: cloudspec.NewCloudSpecAPI(facadeCaller, modelTag), 41 }, nil 42 } 43 44 // BestAPIVersion returns the API version that we were able to 45 // determine is supported by both the client and the API Server. 46 func (c *Client) BestAPIVersion() int { 47 return c.facade.BestAPIVersion() 48 } 49 50 // ModelTag returns the current model's tag. 51 func (c *Client) ModelTag() (names.ModelTag, bool) { 52 return c.facade.RawAPICaller().ModelTag() 53 } 54 55 // life requests the life cycle of the given entity from the server. 56 func (c *Client) life(tag names.Tag) (params.Life, error) { 57 return common.OneLife(c.facade, tag) 58 } 59 60 // Unit provides access to methods of a state.Unit through the facade. 61 func (c *Client) Unit(tag names.UnitTag) (*Unit, error) { 62 life, err := c.life(tag) 63 if err != nil { 64 return nil, err 65 } 66 return &Unit{ 67 tag: tag, 68 life: life, 69 st: c, 70 }, nil 71 } 72 73 // Machine provides access to methods of a state.Machine through the 74 // facade. 75 func (c *Client) Machine(tag names.MachineTag) (*Machine, error) { 76 life, err := c.life(tag) 77 if err != nil { 78 return nil, err 79 } 80 return &Machine{ 81 tag: tag, 82 life: life, 83 st: c, 84 }, nil 85 } 86 87 // WatchModelMachines returns a StringsWatcher that notifies of 88 // changes to the life cycles of the top level machines in the current 89 // model. 90 func (c *Client) WatchModelMachines() (watcher.StringsWatcher, error) { 91 var result params.StringsWatchResult 92 err := c.facade.FacadeCall("WatchModelMachines", nil, &result) 93 if err != nil { 94 return nil, err 95 } 96 if err := result.Error; err != nil { 97 return nil, result.Error 98 } 99 w := apiwatcher.NewStringsWatcher(c.facade.RawAPICaller(), result) 100 return w, nil 101 } 102 103 // WatchOpenedPorts returns a StringsWatcher that notifies of 104 // changes to the opened ports for the current model. 105 func (c *Client) WatchOpenedPorts() (watcher.StringsWatcher, error) { 106 modelTag, ok := c.ModelTag() 107 if !ok { 108 return nil, errors.New("API connection is controller-only (should never happen)") 109 } 110 var results params.StringsWatchResults 111 args := params.Entities{ 112 Entities: []params.Entity{{Tag: modelTag.String()}}, 113 } 114 if err := c.facade.FacadeCall("WatchOpenedPorts", args, &results); err != nil { 115 return nil, err 116 } 117 if len(results.Results) != 1 { 118 return nil, errors.Errorf("expected 1 result, got %d", len(results.Results)) 119 } 120 result := results.Results[0] 121 if err := result.Error; err != nil { 122 return nil, result.Error 123 } 124 w := apiwatcher.NewStringsWatcher(c.facade.RawAPICaller(), result) 125 return w, nil 126 } 127 128 // Relation provides access to methods of a state.Relation through the 129 // facade. 130 func (c *Client) Relation(tag names.RelationTag) (*Relation, error) { 131 life, err := c.life(tag) 132 if err != nil { 133 return nil, err 134 } 135 return &Relation{ 136 tag: tag, 137 life: life, 138 }, nil 139 } 140 141 // WatchEgressAddressesForRelation returns a watcher that notifies when addresses, 142 // from which connections will originate to the provider side of the relation, change. 143 // Each event contains the entire set of addresses which the provider side is required 144 // to allow for access from the other side of the relation. 145 func (c *Client) WatchEgressAddressesForRelation(relationTag names.RelationTag) (watcher.StringsWatcher, error) { 146 args := params.Entities{[]params.Entity{{Tag: relationTag.String()}}} 147 var results params.StringsWatchResults 148 err := c.facade.FacadeCall("WatchEgressAddressesForRelations", args, &results) 149 if err != nil { 150 return nil, errors.Trace(err) 151 } 152 if len(results.Results) != 1 { 153 return nil, errors.Errorf("expected 1 result, got %d", len(results.Results)) 154 } 155 result := results.Results[0] 156 if result.Error != nil { 157 return nil, result.Error 158 } 159 w := apiwatcher.NewStringsWatcher(c.facade.RawAPICaller(), result) 160 return w, nil 161 } 162 163 // WatchIngressAddressesForRelation returns a watcher that notifies when addresses, 164 // from which connections will originate for the relation, change. 165 // Each event contains the entire set of addresses which are required 166 // for ingress into this model from the other requirer side of the relation. 167 func (c *Client) WatchIngressAddressesForRelation(relationTag names.RelationTag) (watcher.StringsWatcher, error) { 168 args := params.Entities{[]params.Entity{{Tag: relationTag.String()}}} 169 var results params.StringsWatchResults 170 err := c.facade.FacadeCall("WatchIngressAddressesForRelations", args, &results) 171 if err != nil { 172 return nil, errors.Trace(err) 173 } 174 if len(results.Results) != 1 { 175 return nil, errors.Errorf("expected 1 result, got %d", len(results.Results)) 176 } 177 result := results.Results[0] 178 if result.Error != nil { 179 return nil, result.Error 180 } 181 w := apiwatcher.NewStringsWatcher(c.facade.RawAPICaller(), result) 182 return w, nil 183 } 184 185 // ControllerAPIInfoForModels returns the controller api connection details for the specified model. 186 func (c *Client) ControllerAPIInfoForModel(modelUUID string) (*api.Info, error) { 187 modelTag := names.NewModelTag(modelUUID) 188 args := params.Entities{[]params.Entity{{Tag: modelTag.String()}}} 189 var results params.ControllerAPIInfoResults 190 err := c.facade.FacadeCall("ControllerAPIInfoForModels", args, &results) 191 if err != nil { 192 return nil, errors.Trace(err) 193 } 194 if len(results.Results) != 1 { 195 return nil, errors.Errorf("expected 1 result, got %d", len(results.Results)) 196 } 197 result := results.Results[0] 198 if result.Error != nil { 199 return nil, result.Error 200 } 201 return &api.Info{ 202 Addrs: result.Addresses, 203 CACert: result.CACert, 204 ModelTag: modelTag, 205 }, nil 206 } 207 208 // MacaroonForRelation returns the macaroon to use when publishing changes for the relation. 209 func (c *Client) MacaroonForRelation(relationKey string) (*macaroon.Macaroon, error) { 210 relationTag := names.NewRelationTag(relationKey) 211 args := params.Entities{[]params.Entity{{Tag: relationTag.String()}}} 212 var results params.MacaroonResults 213 err := c.facade.FacadeCall("MacaroonForRelations", args, &results) 214 if err != nil { 215 return nil, errors.Trace(err) 216 } 217 if len(results.Results) != 1 { 218 return nil, errors.Errorf("expected 1 result, got %d", len(results.Results)) 219 } 220 result := results.Results[0] 221 if result.Error != nil { 222 return nil, result.Error 223 } 224 return result.Result, nil 225 } 226 227 // SetRelationStatus sets the status for a given relation. 228 func (c *Client) SetRelationStatus(relationKey string, status relation.Status, message string) error { 229 relationTag := names.NewRelationTag(relationKey) 230 args := params.SetStatus{Entities: []params.EntityStatusArgs{ 231 {Tag: relationTag.String(), Status: status.String(), Info: message}, 232 }} 233 234 var results params.ErrorResults 235 err := c.facade.FacadeCall("SetRelationsStatus", args, &results) 236 if err != nil { 237 return errors.Trace(err) 238 } 239 return results.OneError() 240 } 241 242 // FirewallRules returns the firewall rules for the specified known service names. 243 func (c *Client) FirewallRules(knownServices ...string) ([]params.FirewallRule, error) { 244 args := params.KnownServiceArgs{ 245 KnownServices: make([]params.KnownServiceValue, len(knownServices)), 246 } 247 for i, s := range knownServices { 248 args.KnownServices[i] = params.KnownServiceValue(s) 249 } 250 251 var results params.ListFirewallRulesResults 252 err := c.facade.FacadeCall("FirewallRules", args, &results) 253 if err != nil { 254 return nil, errors.Trace(err) 255 } 256 return results.Rules, nil 257 }