Skip to content

Commit f4bb45e

Browse files
committed
* Added better error handling.
* Added example for map downlinks. * Refactored the swim test server.
1 parent fd0c39b commit f4bb45e

File tree

7 files changed

+89
-63
lines changed

7 files changed

+89
-63
lines changed

examples/main.tf

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,25 @@ provider "swim" {
3434
url = "ws://127.0.0.1:9001/"
3535
}
3636

37-
resource "swim_value_downlink" "state" {
38-
node = "/unit"
39-
lane = "state"
37+
resource "swim_value_downlink" "id" {
38+
node = "/container"
39+
lane = "id"
4040
value = docker_container.nginx.id
4141
}
4242

43-
output "status" {
44-
value = swim_value_downlink.state
43+
resource "swim_map_downlink" "ports" {
44+
node = "/container"
45+
lane = "ports"
46+
items = {
47+
"external" = docker_container.nginx.ports[0].external
48+
"internal" = docker_container.nginx.ports[0].internal
49+
}
50+
}
51+
52+
output "id" {
53+
value = swim_value_downlink.id
4554
}
55+
56+
output "ports" {
57+
value = swim_map_downlink.ports
58+
}

swim-server/src/main/java/swim/basic/UnitAgent.java

Lines changed: 17 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -9,49 +9,29 @@
99

1010
public class UnitAgent extends AbstractAgent {
1111

12-
@SwimLane("state")
13-
ValueLane<Value> state = this.<Value>valueLane()
14-
.didSet((newValue, oldValue) -> {
15-
if(!oldValue.isDefinite()){
16-
logMessage("Container id set to " + Recon.toString(newValue));
17-
}
18-
else
19-
{
20-
if (newValue.isDefinite()) {
21-
logMessage("Container id changed from " + Recon.toString(oldValue) + " to " + Recon.toString(newValue));
22-
}
23-
else {
24-
logMessage("Container id cleared");
25-
}
26-
}
27-
});
28-
29-
@SwimLane("cart")
30-
MapLane<String, String> cart = this.<String, String>mapLane()
31-
.didUpdate((key, newValue, oldValue) -> {
32-
logMessage("Item " + key + " value changed to " + newValue + " from " + oldValue);
33-
})
34-
.didRemove((key, oldValue) -> {
35-
logMessage("Item removed <" + key + "," + oldValue + ">");
36-
});
37-
38-
@SwimLane("state2")
39-
ValueLane<Value> state2 = this.<Value>valueLane()
12+
@SwimLane("id")
13+
ValueLane<Value> id = this.<Value>valueLane()
4014
.didSet((newValue, oldValue) -> {
41-
if(!oldValue.isDefinite()){
42-
logMessage("Container id2 set to " + Recon.toString(newValue));
43-
}
44-
else
45-
{
15+
if (!oldValue.isDefinite()) {
16+
logMessage("Container id set to " + Recon.toString(newValue));
17+
} else {
4618
if (newValue.isDefinite()) {
47-
logMessage("Container id2 changed from " + Recon.toString(oldValue) + " to " + Recon.toString(newValue));
48-
}
49-
else {
50-
logMessage("Container id2 cleared");
19+
logMessage("Container id changed from " + Recon.toString(oldValue) + " to " + Recon.toString(newValue));
20+
} else {
21+
logMessage("Container id cleared");
5122
}
5223
}
5324
});
5425

26+
@SwimLane("ports")
27+
MapLane<String, String> ports = this.<String, String>mapLane()
28+
.didUpdate((key, newValue, oldValue) -> {
29+
logMessage("Port " + key + " value changed to " + newValue + " from " + oldValue);
30+
})
31+
.didRemove((key, oldValue) -> {
32+
logMessage("Port removed <" + key + "," + oldValue + ">");
33+
}).didClear(() -> logMessage("All ports removed"));
34+
5535
@Override
5636
public void didStart() {
5737
logMessage("did start");

swim-server/src/main/resources/server.recon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
basic: @fabric {
1212
@plane(class: "swim.basic.BasicPlane")
1313
@node {
14-
uri: "/unit"
14+
uri: "/container"
1515
@agent(class: "swim.basic.UnitAgent")
1616
}
1717
}

swim/provider.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ func Provider() *schema.Provider {
1616
DefaultFunc: schema.EnvDefaultFunc("SWIM_URL", nil),
1717
},
1818
},
19-
// Todo change this
2019
ResourcesMap: map[string]*schema.Resource{
2120
"swim_value_downlink": resourceValueDownlink(),
2221
"swim_map_downlink": resourceMapDownlink(),

swim/resource_map_downlink.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,20 +61,20 @@ func resourceMapDownlinkCreate(ctx context.Context, data *schema.ResourceData, m
6161
lane := data.Get("lane").(string)
6262
items, setItems := data.GetOk("items")
6363

64-
data.SetId(node + "/" + lane)
65-
6664
if setItems {
6765
diags := client.SetMapDownlink(node, lane, items.(map[string]interface{}))
66+
if diags == nil {
67+
data.SetId(node + "/" + lane)
68+
}
6869
return diags
6970
} else {
7071
items, diags := client.GetMapDownlink(node, lane)
71-
if diags != nil {
72-
return diags
73-
} else {
72+
if diags == nil {
73+
data.SetId(node + "/" + lane)
7474
data.Set("items", items)
75-
var diags diag.Diagnostics
76-
return diags
7775
}
76+
return diags
77+
7878
}
7979
}
8080

swim/resource_value_downlink.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,20 +56,19 @@ func resourceValueDownlinkCreate(ctx context.Context, data *schema.ResourceData,
5656
lane := data.Get("lane").(string)
5757
value, setValue := data.GetOk("value")
5858

59-
data.SetId(node + "/" + lane)
60-
6159
if setValue {
6260
diags := client.SetValueDownlink(node, lane, value.(string))
61+
if diags == nil {
62+
data.SetId(node + "/" + lane)
63+
}
6364
return diags
6465
} else {
6566
value, diags := client.GetValueDownlink(node, lane)
66-
if diags != nil {
67-
return diags
68-
} else {
67+
if diags == nil {
68+
data.SetId(node + "/" + lane)
6969
data.Set("value", value)
70-
var diags diag.Diagnostics
71-
return diags
7270
}
71+
return diags
7372
}
7473
}
7574

swim/swim_client.go

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,34 @@ import (
44
"fmt"
55
"regexp"
66
"strings"
7+
"time"
78

89
"github.com/gorilla/websocket"
910
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
1011
)
1112

13+
const (
14+
// Time allowed to write a message.
15+
writeWait = 5 * time.Second
16+
// Time allowed to read a message.
17+
readWait = 5 * time.Second
18+
// Maximum message size.
19+
maxMessageSize = 512
20+
)
21+
1222
type SwimClient struct {
1323
url string
1424
}
1525

16-
//Todo add deadlines https://github.com/gorilla/websocket/blob/af47554f343b4675b30172ac301638d350db34a5/examples/chat/client.go#L91
17-
//Todo add error for lane not found
1826
//Todo refactor duplications
1927

2028
// ------------------- Value Downlink Operations -------------------
2129
func (client SwimClient) GetValueDownlink(node string, lane string) (string, diag.Diagnostics) {
2230
conn, _, err := websocket.DefaultDialer.Dial(client.url, nil)
31+
conn.SetReadLimit(maxMessageSize)
32+
conn.SetReadDeadline(time.Now().Add(readWait))
33+
conn.SetWriteDeadline(time.Now().Add(writeWait))
34+
2335
defer conn.Close()
2436

2537
value := ""
@@ -37,24 +49,31 @@ func (client SwimClient) GetValueDownlink(node string, lane string) (string, dia
3749

3850
for {
3951
_, resp, err := conn.ReadMessage()
40-
response := string(resp)
4152

4253
if err != nil {
4354
return value, diag.FromErr(err)
4455
} else {
56+
response := string(resp)
4557
if strings.HasPrefix(response, "@event") {
4658
re := regexp.MustCompile(`^@event\(.*\)(.*?)$`)
4759
match := re.FindStringSubmatch(response)
4860
value = string(match[1])
4961
} else if strings.HasPrefix(response, "@synced") {
50-
return value, nil
62+
return value, diag.FromErr(err)
63+
} else if strings.HasSuffix(response, "@laneNotFound") {
64+
return value, diag.Errorf("Lane %q on node %q not found", lane, node)
65+
} else if strings.HasSuffix(response, "@nodeNotFound") {
66+
return value, diag.Errorf("Node %q not found", node)
5167
}
5268
}
5369
}
5470
}
5571

5672
func (client SwimClient) SetValueDownlink(node string, lane string, value string) diag.Diagnostics {
5773
conn, _, err := websocket.DefaultDialer.Dial(client.url, nil)
74+
conn.SetReadLimit(maxMessageSize)
75+
conn.SetReadDeadline(time.Now().Add(readWait))
76+
conn.SetWriteDeadline(time.Now().Add(writeWait))
5877
defer conn.Close()
5978

6079
if err != nil {
@@ -73,6 +92,9 @@ func (client SwimClient) SetValueDownlink(node string, lane string, value string
7392

7493
func (client SwimClient) ClearValueDownlink(node string, lane string) diag.Diagnostics {
7594
conn, _, err := websocket.DefaultDialer.Dial(client.url, nil)
95+
conn.SetReadLimit(maxMessageSize)
96+
conn.SetReadDeadline(time.Now().Add(readWait))
97+
conn.SetWriteDeadline(time.Now().Add(writeWait))
7698
defer conn.Close()
7799

78100
if err != nil {
@@ -92,6 +114,9 @@ func (client SwimClient) ClearValueDownlink(node string, lane string) diag.Diagn
92114
// ------------------- Map Downlink Operations -------------------
93115
func (client SwimClient) GetMapDownlink(node string, lane string) (map[string]string, diag.Diagnostics) {
94116
conn, _, err := websocket.DefaultDialer.Dial(client.url, nil)
117+
conn.SetReadLimit(maxMessageSize)
118+
conn.SetReadDeadline(time.Now().Add(readWait))
119+
conn.SetWriteDeadline(time.Now().Add(writeWait))
95120
defer conn.Close()
96121

97122
items := make(map[string]string)
@@ -109,24 +134,31 @@ func (client SwimClient) GetMapDownlink(node string, lane string) (map[string]st
109134

110135
for {
111136
_, resp, err := conn.ReadMessage()
112-
response := string(resp)
113137

114138
if err != nil {
115139
return items, diag.FromErr(err)
116140
} else {
141+
response := string(resp)
117142
if strings.HasPrefix(response, "@event") {
118143
re := regexp.MustCompile(`^@event\(.*\)@update\(key:(.*?)\)(.*?)$`)
119144
match := re.FindStringSubmatch(response)
120145
items[match[1]] = match[2]
121146
} else if strings.HasPrefix(response, "@synced") {
122147
return items, nil
148+
} else if strings.HasSuffix(response, "@laneNotFound") {
149+
return items, diag.Errorf("Lane %q on node %q not found", lane, node)
150+
} else if strings.HasSuffix(response, "@nodeNotFound") {
151+
return items, diag.Errorf("Node %q not found", node)
123152
}
124153
}
125154
}
126155
}
127156

128157
func (client SwimClient) SetMapDownlink(node string, lane string, items map[string]interface{}) diag.Diagnostics {
129158
conn, _, err := websocket.DefaultDialer.Dial(client.url, nil)
159+
conn.SetReadLimit(maxMessageSize)
160+
conn.SetReadDeadline(time.Now().Add(readWait))
161+
conn.SetWriteDeadline(time.Now().Add(writeWait))
130162
defer conn.Close()
131163

132164
if err != nil {
@@ -154,6 +186,9 @@ func (client SwimClient) SetMapDownlink(node string, lane string, items map[stri
154186

155187
func (client SwimClient) ClearMapDownlink(node string, lane string) diag.Diagnostics {
156188
conn, _, err := websocket.DefaultDialer.Dial(client.url, nil)
189+
conn.SetReadLimit(maxMessageSize)
190+
conn.SetReadDeadline(time.Now().Add(readWait))
191+
conn.SetWriteDeadline(time.Now().Add(writeWait))
157192
defer conn.Close()
158193

159194
if err != nil {

0 commit comments

Comments
 (0)