conlink 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/.dockerignore +5 -0
  2. package/Dockerfile +34 -0
  3. package/LICENSE +373 -0
  4. package/README.md +485 -0
  5. package/TODO +34 -0
  6. package/conlink +11 -0
  7. package/conlink-start.sh +172 -0
  8. package/examples/dot.js +36 -0
  9. package/examples/index.html +11 -0
  10. package/examples/net2dot.yaml +21 -0
  11. package/examples/test1-compose.yaml +60 -0
  12. package/examples/test2-compose.yaml +31 -0
  13. package/examples/test2-network.yaml +5 -0
  14. package/examples/test3-network.yaml +5 -0
  15. package/examples/test4-multiple/all-compose.yaml +5 -0
  16. package/examples/test4-multiple/base-compose.yaml +25 -0
  17. package/examples/test4-multiple/node1-compose.yaml +17 -0
  18. package/examples/test4-multiple/nodes2-compose.yaml +20 -0
  19. package/examples/test4-multiple/web-network.yaml +2 -0
  20. package/examples/test5-geneve-compose.yaml +31 -0
  21. package/examples/test6-cfn.yaml +184 -0
  22. package/examples/test7-compose.yaml +31 -0
  23. package/examples/test8-compose.yaml +35 -0
  24. package/host-build.yaml +1 -0
  25. package/inspect.json +210 -0
  26. package/link-add.sh +197 -0
  27. package/link-del.sh +60 -0
  28. package/net2dot +11 -0
  29. package/notes.txt +82 -0
  30. package/old/Dockerfile.bak +26 -0
  31. package/old/add-link.sh +82 -0
  32. package/old/conlink +12 -0
  33. package/old/conlink.cljs +131 -0
  34. package/old/dot_gitignore +1 -0
  35. package/old/examples/test2-compose.yaml +32 -0
  36. package/old/examples/test2-network.yaml +42 -0
  37. package/old/move-link.sh +108 -0
  38. package/old/net2dot.py +122 -0
  39. package/old/notes-old.txt +97 -0
  40. package/old/package.json +16 -0
  41. package/old/schema.yaml +138 -0
  42. package/old/schema.yaml.bak +76 -0
  43. package/old/test2b-compose.yaml +18 -0
  44. package/old/veth-link.sh +96 -0
  45. package/package.json +15 -0
  46. package/schema-ish.yaml +29 -0
  47. package/schema.yaml +71 -0
  48. package/shadow-cljs.edn +33 -0
  49. package/src/conlink/addrs.cljc +63 -0
  50. package/src/conlink/core.cljs +772 -0
  51. package/src/conlink/net2dot.cljs +158 -0
  52. package/src/conlink/util.cljs +140 -0
  53. package/tests/invalid-schema-1.yaml +6 -0
  54. package/tests/invalid-schema-2.yaml +6 -0
  55. package/tests/invalid-schema-3.yaml +17 -0
  56. package/tests/invalid-schema-4.yaml +14 -0
  57. package/tests/invalid-schema-5.yaml +12 -0
  58. package/tests/invalid-schema-6.yaml +12 -0
  59. package/tmp/conlink/.env +1 -0
@@ -0,0 +1,36 @@
1
+ // engines:
2
+ // - dot: reasonable but elongated
3
+ // - fdp: good fit but tons of crossing lines
4
+ // - osage: boxes tightly packet, no layout on lines
5
+ //
6
+ // - neato: overlapping clusters/groups
7
+ // - patchwork: one packed box, no visible lines
8
+ // - circo: sparse rectilinear layout, no clusters/groups
9
+ // - twopi: circo-like with diagonals, no clusters/groups
10
+ const DEFAULT_ENGINE = 'dot'
11
+
12
+ function downloadSVG(container) {
13
+ const svg = document.getElementById(container).innerHTML;
14
+ const blob = new Blob([svg.toString()]);
15
+ const element = document.createElement("a");
16
+ element.download = `${container}.svg`;
17
+ element.href = window.URL.createObjectURL(blob);
18
+ element.click();
19
+ element.remove();
20
+ }
21
+
22
+ const params = new URLSearchParams(location.search)
23
+
24
+ const dotFile = params.get('data') || 'data.dot'
25
+ const engine = params.get('engine') || DEFAULT_ENGINE
26
+ console.log(`Fetching '${dotFile}'`)
27
+ fetch(dotFile)
28
+ .then(resp => resp.text())
29
+ .then(text => {
30
+ console.log(`Loaded dot data:\n`, text)
31
+ console.log(`Rendering using engine '${engine}'`)
32
+ d3.select('#graph')
33
+ .graphviz()
34
+ .engine(engine)
35
+ .renderDot(text)
36
+ })
@@ -0,0 +1,11 @@
1
+ <!DOCTYPE html>
2
+ <meta charset="utf-8">
3
+ <body>
4
+ <script src="//d3js.org/d3.v5.min.js"></script>
5
+ <script src="https://unpkg.com/@hpcc-js/wasm@0.3.11/dist/index.min.js"></script>
6
+ <script src="https://unpkg.com/d3-graphviz@3.0.5/build/d3-graphviz.js"></script>
7
+ <script src="dot.js"></script>
8
+ <div id="graph" style="text-align: center;"></div>
9
+ <br><br>
10
+ <button onclick="downloadSVG('graph')">Download SVG</button>
11
+ </body>
@@ -0,0 +1,21 @@
1
+ links:
2
+ - {service: nodeA, bridge: s1, dev: e1}
3
+ - {service: nodeA, bridge: s2, dev: e2}
4
+ - {service: nodeA, bridge: s3, dev: e3}
5
+ - {service: nodeB, bridge: s2}
6
+
7
+ - {container: nodeC, bridge: s3}
8
+
9
+ - {type: dummy, container: nodeD, dev: dummy0}
10
+
11
+ - {type: vlan, service: nodeE, dev: v0, outer-dev: eni0, vlanid: 5}
12
+ - {type: macvlan, service: nodeE, dev: mv0, outer-dev: eni0, mode: bridge}
13
+ - {type: macvlan, service: nodeF, dev: mv0, outer-dev: eni0, mode: bridge}
14
+ - {type: ipvlan, service: nodeG, dev: iv0, outer-dev: eni1, mode: bridge}
15
+ - {type: macvlan, service: nodeH, dev: mv0, outer-dev: eni1, mode: bridge}
16
+
17
+ tunnels:
18
+ - {type: geneve, bridge: s1, vni: 1001, remote: "${REMOTE1}"}
19
+ - {type: geneve, bridge: s3, vni: 1002, remote: "${REMOTE2}"}
20
+
21
+
@@ -0,0 +1,60 @@
1
+ # Test Topology:
2
+ #
3
+ # r0
4
+ # /|\
5
+ # / | \
6
+ # s1 s2 s3
7
+ # / | \
8
+ # / | \
9
+ # h1 h2 h3
10
+ #
11
+
12
+ version: "2.4"
13
+
14
+ services:
15
+ r0:
16
+ image: alpine
17
+ network_mode: none
18
+ command: "sleep 864000"
19
+ x-network:
20
+ links:
21
+ - {bridge: s1, dev: eth-s1, ip: "192.168.1.1/24"}
22
+ - {bridge: s2, dev: eth-s2, ip: "172.16.0.1/12"}
23
+ - {bridge: s3, dev: eth-s3, ip: "10.0.0.1/8"}
24
+
25
+ h1:
26
+ image: alpine
27
+ network_mode: none
28
+ command: "sleep 864000"
29
+ x-network:
30
+ links:
31
+ - {bridge: s1, ip: "192.168.1.100/24", route: "default via 192.168.1.1"}
32
+
33
+ h2:
34
+ image: alpine
35
+ network_mode: none
36
+ command: "sleep 864000"
37
+ x-network:
38
+ links:
39
+ - {bridge: s2, ip: "172.16.0.100/12", route: "default via 172.16.0.1"}
40
+
41
+ h3:
42
+ image: alpine
43
+ network_mode: none
44
+ command: "sleep 864000"
45
+ x-network:
46
+ links:
47
+ - {bridge: s3, ip: "10.0.0.100/8", route: "default via 10.0.0.1"}
48
+
49
+ network:
50
+ build: {context: ../}
51
+ image: conlink
52
+ pid: host
53
+ network_mode: none
54
+ cap_add: [SYS_ADMIN, NET_ADMIN, SYS_NICE, NET_BROADCAST, IPC_LOCK]
55
+ security_opt: [ 'apparmor:unconfined' ] # needed on Ubuntu 18.04
56
+ volumes:
57
+ - /var/run/docker.sock:/var/run/docker.sock
58
+ - /var/lib/docker:/var/lib/docker
59
+ - ./:/test
60
+ command: /app/build/conlink.js --compose-file /test/test1-compose.yaml
@@ -0,0 +1,31 @@
1
+ # A docker-compose file with an external network configuration file
2
+ # and docker containers that are connected via a switch. The
3
+ # "internet" container is setup that is also connected to the switch
4
+ # and is listening on 8.8.8.8 (to test routing from the nodes).
5
+
6
+ version: "2.4"
7
+
8
+ services:
9
+ network:
10
+ build: {context: ../}
11
+ image: conlink
12
+ pid: host
13
+ network_mode: none
14
+ cap_add: [SYS_ADMIN, NET_ADMIN, SYS_NICE, NET_BROADCAST, IPC_LOCK]
15
+ security_opt: [ 'apparmor:unconfined' ] # needed on Ubuntu 18.04
16
+ volumes:
17
+ - /var/run/docker.sock:/var/run/docker.sock
18
+ - /var/lib/docker:/var/lib/docker
19
+ - ./:/test
20
+ command: /app/build/conlink.js --compose-file /test/test2-compose.yaml --network-file /test/test2-network.yaml
21
+
22
+ node:
23
+ image: alpine
24
+ network_mode: none
25
+ scale: 2
26
+ command: sh -c 'while ! ip link show eth0 up; do sleep 1; done; sleep 864000'
27
+
28
+ internet:
29
+ image: alpine
30
+ network_mode: none
31
+ command: sleep 864000
@@ -0,0 +1,5 @@
1
+ links:
2
+ - {service: node, bridge: s1, dev: eth0, ip: 10.0.1.1/16, route: "default via 10.0.0.1"}
3
+
4
+ - {service: internet, bridge: s1, dev: eth0, ip: 10.0.0.1/16}
5
+ - {service: internet, type: dummy, dev: i0, ip: 8.8.8.8/24}
@@ -0,0 +1,5 @@
1
+
2
+ links:
3
+ - {container: "${NODE_NAME_1}", bridge: s1, dev: ext-intf, ip: 10.0.1.1/16}
4
+ - {container: "${NODE_NAME_2}", bridge: s1, dev: ext-intf, ip: 10.0.1.2/16}
5
+
@@ -0,0 +1,5 @@
1
+ version: "2.4"
2
+
3
+ services:
4
+ network:
5
+ command: /app/build/conlink.js --compose-file ${COMPOSE_FILE:-examples/test4-multiple/base-compose.yaml:examples/test4-multiple/node1-compose.yaml:examples/test4-multiple/nodes2.yaml:examples/test4-multiple/all-compose.yaml} --network-file examples/test4-multiple/web-network.yaml
@@ -0,0 +1,25 @@
1
+ version: "2.4"
2
+
3
+ services:
4
+ r0:
5
+ image: python:3-alpine
6
+ network_mode: none
7
+ command: sleep 864000
8
+ x-network:
9
+ links:
10
+ - {bridge: s0, dev: e0, ip: "10.0.0.100/24"}
11
+
12
+ network:
13
+ build: {context: ../..}
14
+ image: conlink
15
+ pid: host
16
+ network_mode: none
17
+ cap_add: [SYS_ADMIN, NET_ADMIN, SYS_NICE, NET_BROADCAST, IPC_LOCK]
18
+ security_opt: [ 'apparmor:unconfined' ] # needed on Ubuntu 18.04
19
+ volumes:
20
+ - /var/run/docker.sock:/var/run/docker.sock
21
+ - /var/lib/docker:/var/lib/docker
22
+ - ../../:/test
23
+ working_dir: /test
24
+ command: /app/build/conlink.js --compose-file ${COMPOSE_FILE:-examples/test4-multiple/base-compose.yaml}
25
+
@@ -0,0 +1,17 @@
1
+ version: "2.4"
2
+
3
+ x-network:
4
+ links:
5
+ - {service: r0, bridge: s1, dev: e1, ip: "10.1.0.100/24"}
6
+
7
+ services:
8
+ network:
9
+ command: /app/build/conlink.js --compose-file ${COMPOSE_FILE:-examples/test4-multiple/node1-compose.yaml}
10
+
11
+ node1:
12
+ image: alpine
13
+ network_mode: none
14
+ command: sleep 864000
15
+ x-network:
16
+ links:
17
+ - {bridge: s1, ip: "10.1.0.1/16", route: "default via 10.1.0.100"}
@@ -0,0 +1,20 @@
1
+ version: "2.4"
2
+
3
+ x-network:
4
+ links:
5
+ - {service: r0, bridge: s2, dev: e2, ip: "10.2.0.100/24"}
6
+
7
+
8
+ services:
9
+ network:
10
+ command: /app/build/conlink.js --compose-file ${COMPOSE_FILE:-examples/test4-multiple/nodes2-compose.yaml}
11
+
12
+ node2:
13
+ image: alpine
14
+ scale: 2
15
+ network_mode: none
16
+ command: sleep 864000
17
+ x-network:
18
+ links:
19
+ - {bridge: s2, ip: "10.2.0.1/16", route: "default via 10.2.0.100"}
20
+
@@ -0,0 +1,2 @@
1
+ commands:
2
+ - {service: r0, command: "python3 -m http.server 80"}
@@ -0,0 +1,31 @@
1
+ x-network:
2
+ tunnels:
3
+ - {type: geneve, bridge: s1, vni: 1001, remote: "${REMOTE}"}
4
+
5
+ services:
6
+ network:
7
+ build: {context: ../}
8
+ image: conlink
9
+ pid: host
10
+ cap_add: [SYS_ADMIN, NET_ADMIN, SYS_NICE, NET_BROADCAST, IPC_LOCK]
11
+ security_opt: [ 'apparmor:unconfined' ] # needed on Ubuntu 18.04
12
+ volumes:
13
+ - /var/run/docker.sock:/var/run/docker.sock
14
+ - /var/lib/docker:/var/lib/docker
15
+ - ./:/test
16
+ environment:
17
+ - REMOTE=${REMOTE:?REMOTE must be set}
18
+ - NODE_IP=${NODE_IP:?NODE_IP must be set}
19
+ ports:
20
+ - "8472:8472/udp" # vxlan default (Linux, ovs is 4789)
21
+ - "6081:6081/udp" # geneve default
22
+ command: /app/build/conlink.js --compose-file /test/test5-geneve-compose.yaml
23
+
24
+ node:
25
+ image: alpine
26
+ network_mode: none
27
+ command: sleep 864000
28
+ x-network:
29
+ links:
30
+ - {bridge: s1, ip: "${NODE_IP}/24"}
31
+
@@ -0,0 +1,184 @@
1
+ AWSTemplateFormatVersion: '2010-09-09'
2
+ Description: Launch conlink on two instances that are connected by an overlay/tunnel network
3
+
4
+ Parameters:
5
+ VpcId:
6
+ Type: AWS::EC2::VPC::Id
7
+ Description: VPCId of Virtual Private Cloud (VPC).
8
+
9
+ SubnetId:
10
+ Description: The ID of the subnet to launch the instances into.
11
+ Type: AWS::EC2::Subnet::Id
12
+
13
+ KeyPairName:
14
+ Description: Keypair associated with the EC2 instance
15
+ Type: AWS::EC2::KeyPair::KeyName
16
+ ConstraintDescription: Must provide a keypair to be associated with the EC2 instance
17
+
18
+ InstanceType:
19
+ Description: AWS instance type for conlink hosts
20
+ Type: String
21
+ Default: m6i.large
22
+
23
+ CidrIp:
24
+ Description: Allowed CIDR addresses for external access to instances
25
+ Type: String
26
+ AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$
27
+ ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/x
28
+ Default: '10.0.0.0/8'
29
+
30
+ Mappings:
31
+ RegionMap:
32
+ us-east-1:
33
+ AMI: "ami-0fc5d935ebf8bc3bc" # Ubuntu 22.04 LTS amd64 jammy (built 2023-09-19)
34
+ us-west-2:
35
+ AMI: "ami-0efcece6bed30fd98" # Ubuntu 22.04 LTS amd64 jammy (built 2023-09-19)
36
+
37
+
38
+ Resources:
39
+
40
+ SecurityGroup:
41
+ Type: AWS::EC2::SecurityGroup
42
+ Properties:
43
+ VpcId: !Ref 'VpcId'
44
+ GroupDescription: Conlink test security group
45
+ SecurityGroupIngress:
46
+ - {IpProtocol: tcp, Description: "SSH", FromPort: 22, ToPort: 22, CidrIp: !Ref 'CidrIp'}
47
+ SecurityGroupEgress:
48
+ - {IpProtocol: '-1', Description: "All outbound", CidrIp: '0.0.0.0/0'}
49
+
50
+ SecurityGroupInternal: # Allow full inter-group communication (Geneve)
51
+ Type: AWS::EC2::SecurityGroupIngress
52
+ Properties: {GroupId: !Ref SecurityGroup, IpProtocol: -1, FromPort: -1, ToPort: -1, SourceSecurityGroupId: !GetAtt SecurityGroup.GroupId }
53
+
54
+
55
+ BaseUserData:
56
+ Type: AWS::SSM::Parameter
57
+ Properties:
58
+ Type: String
59
+ Value: !Sub |
60
+ # Uncomment to allow root login using KeyPairName
61
+ #sed -i "s/^.* ssh-rsa/ssh-rsa/" /root/.ssh/authorized_keys
62
+
63
+ apt-get -y update
64
+ apt-get -y install ca-certificates curl gnupg lsb-release
65
+ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
66
+
67
+ # docker repo
68
+ echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
69
+
70
+ # install docker and docker-compose
71
+ apt-get -y update
72
+ apt-get -y install git docker-ce docker-ce-cli
73
+ curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
74
+ chmod +x /usr/local/bin/docker-compose
75
+
76
+ # kernel modules needed by conlink
77
+ modprobe openvswitch
78
+ modprobe geneve
79
+
80
+ ## Uncomment below to install/configure podman
81
+ # # podman repo
82
+ # . /etc/os-release
83
+ # curl -L "https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_$VERSION_ID/Release.key" | apt-key add -
84
+ # echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_$VERSION_ID/ /" | tee /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
85
+ # apt-get -y install podman containerd.io
86
+ # ## enable and trigger systemd/dbus for ubuntu user
87
+ # loginctl enable-linger ubuntu
88
+ # echo "podman ps" | sudo -i -u ubuntu bash
89
+
90
+ ## Download conlink image and repo
91
+ docker pull lonocloud/conlink:config-and-cljs-refactor
92
+ git clone https://github.com/LonoCloud/conlink /root/conlink
93
+ cd /root/conlink
94
+ git checkout -b config-and-cljs-refactor origin/config-and-cljs-refactor
95
+
96
+ #cfn-signal -e 0 --stack ${AWS::StackName} --region ${AWS::Region} --resource WaitHandle
97
+ cat > /tmp/signal << EOF
98
+ {
99
+ "Status": "SUCCESS",
100
+ "Reason": "Configuration complete",
101
+ "UniqueId": "$NODE_IP",
102
+ "Data": "REMOTE: $REMOTE, NODE_IP: $NODE_IP"
103
+ }
104
+ EOF
105
+ curl -T /tmp/signal "${WaitHandle}"
106
+
107
+ ## Start test5 example using conlink
108
+ sed -i 's@image: .*conlink@image: lonocloud/conlink:config-and-cljs-refactor@' examples/test5-geneve-compose.yaml
109
+ echo "REMOTE=$REMOTE" > .env
110
+ echo "NODE_IP=$NODE_IP" >> .env
111
+ docker-compose --env-file .env -f examples/test5-geneve-compose.yaml up --force-recreate
112
+
113
+
114
+ Eni1:
115
+ Type: AWS::EC2::NetworkInterface
116
+ Properties:
117
+ GroupSet: [!Ref 'SecurityGroup']
118
+ Description: Instance1 ENI
119
+ SubnetId: !Ref 'SubnetId'
120
+
121
+ Eni2:
122
+ Type: AWS::EC2::NetworkInterface
123
+ Properties:
124
+ GroupSet: [!Ref 'SecurityGroup']
125
+ Description: Instance2 ENI
126
+ SubnetId: !Ref 'SubnetId'
127
+
128
+ UserData1:
129
+ Type: AWS::SSM::Parameter
130
+ Properties:
131
+ Type: String
132
+ Value: !Sub |
133
+ #!/bin/bash
134
+ set -x
135
+ export REMOTE=${Eni2.PrimaryPrivateIpAddress} NODE_IP=192.168.100.1
136
+ ${BaseUserData.Value}
137
+
138
+ UserData2:
139
+ Type: AWS::SSM::Parameter
140
+ Properties:
141
+ Type: String
142
+ Value: !Sub |
143
+ #!/bin/bash
144
+ set -x
145
+ export REMOTE=${Eni1.PrimaryPrivateIpAddress} NODE_IP=192.168.100.2
146
+ ${BaseUserData.Value}
147
+
148
+
149
+ Instance1:
150
+ Type: AWS::EC2::Instance
151
+ Properties:
152
+ InstanceType: !Ref InstanceType
153
+ ImageId: !FindInMap [RegionMap, !Ref "AWS::Region", AMI]
154
+ KeyName: !Ref 'KeyPairName'
155
+ NetworkInterfaces: [{NetworkInterfaceId: !Ref 'Eni1', DeviceIndex: '0'}]
156
+ UserData: {Fn::Base64: !Sub "${UserData1.Value}"}
157
+
158
+ Instance2:
159
+ Type: AWS::EC2::Instance
160
+ Properties:
161
+ InstanceType: !Ref InstanceType
162
+ ImageId: !FindInMap [RegionMap, !Ref "AWS::Region", AMI]
163
+ KeyName: !Ref 'KeyPairName'
164
+ NetworkInterfaces: [{NetworkInterfaceId: !Ref 'Eni2', DeviceIndex: '0'}]
165
+ UserData: {Fn::Base64: !Sub "${UserData2.Value}"}
166
+
167
+ WaitHandle:
168
+ Type: "AWS::CloudFormation::WaitConditionHandle"
169
+ Properties: {}
170
+ WaitConfigured:
171
+ Type: AWS::CloudFormation::WaitCondition
172
+ DependsOn: [Instance1, Instance2]
173
+ Properties:
174
+ Handle: !Ref WaitHandle
175
+ Count: 2
176
+ Timeout: 1200 # 20 minutes timeout
177
+
178
+
179
+ Outputs:
180
+ Instance1Id: {Value: !Ref Instance1}
181
+ Instance2Id: {Value: !Ref Instance2}
182
+
183
+ Instance1Ip: {Value: !GetAtt Eni1.PrimaryPrivateIpAddress}
184
+ Instance2Ip: {Value: !GetAtt Eni2.PrimaryPrivateIpAddress}
@@ -0,0 +1,31 @@
1
+ # A docker-compose file with embedded network config that demonstrates
2
+ # MAC, MTU, and NetEm settings
3
+
4
+ version: "2.4"
5
+
6
+ services:
7
+ network:
8
+ build: {context: ../}
9
+ image: conlink
10
+ pid: host
11
+ network_mode: none
12
+ cap_add: [SYS_ADMIN, NET_ADMIN, SYS_NICE, NET_BROADCAST, IPC_LOCK]
13
+ security_opt: [ 'apparmor:unconfined' ] # needed on Ubuntu 18.04
14
+ volumes:
15
+ - /var/run/docker.sock:/var/run/docker.sock
16
+ - /var/lib/docker:/var/lib/docker
17
+ - ./:/test
18
+ command: /app/build/conlink.js --compose-file /test/test7-compose.yaml
19
+
20
+ node:
21
+ image: alpine
22
+ network_mode: none
23
+ scale: 2
24
+ command: "sleep 864000"
25
+ x-network:
26
+ links:
27
+ - bridge: s1
28
+ ip: 10.0.1.1/16
29
+ mac: 00:0a:0b:0c:0d:01
30
+ mtu: 4111
31
+ netem: "delay 40ms rate 10mbit"
@@ -0,0 +1,35 @@
1
+ version: "2.4"
2
+
3
+ services:
4
+ node-macvlan: &node-macvlan
5
+ image: python:3-alpine
6
+ network_mode: none
7
+ command: sh -c 'while ! ip link show eth0 up; do sleep 1; done; python3 -m http.server --bind 10.0.1.1 80'
8
+ x-network:
9
+ links:
10
+ - {type: dummy, dev: d0, ip: 10.0.1.1/24}
11
+ - {type: macvlan, mode: bridge, outer-dev: "${HOST_INTERFACE}", ip: "${NODE1_HOST_ADDRESS}", nat: 10.0.1.1}
12
+
13
+ node-vlan:
14
+ <<: *node-macvlan
15
+ x-network:
16
+ links:
17
+ - {type: dummy, dev: d0, ip: 10.0.1.1/24}
18
+ - {type: vlan, vlanid: 5, outer-dev: "${HOST_INTERFACE}", ip: "${NODE2_HOST_ADDRESS}", nat: 10.0.1.1}
19
+
20
+ network:
21
+ build: {context: ../}
22
+ image: conlink
23
+ pid: host
24
+ network_mode: none
25
+ privileged: true # required for *vlan creation in root ns
26
+ security_opt: [ 'apparmor:unconfined' ] # needed on Ubuntu 18.04
27
+ volumes:
28
+ - /var/run/docker.sock:/var/run/docker.sock
29
+ - /var/lib/docker:/var/lib/docker
30
+ - ./:/test
31
+ environment:
32
+ - HOST_INTERFACE=${HOST_INTERFACE:?HOST_INTERFACE must be set}
33
+ - NODE1_HOST_ADDRESS=${NODE1_HOST_ADDRESS:?NODE1_HOST_ADDRESS must be set}
34
+ - NODE2_HOST_ADDRESS=${NODE2_HOST_ADDRESS:?NODE2_HOST_ADDRESS must be set}
35
+ command: /app/build/conlink.js --compose-file /test/test8-compose.yaml
@@ -0,0 +1 @@
1
+ services: {network: {volumes: ["../build:/app/build"]}}