├── .dockerignore ├── .gitignore ├── .travis.yml ├── .whitesource ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── docker-compose.yml ├── docs ├── index.md ├── k3s.md ├── kube.md └── microk8s.md ├── example ├── simplest-webthing-go │ └── simplest-thing.go └── single-webthing-go │ └── single-thing.go ├── extra └── tools │ ├── docker │ └── debian │ │ └── Dockerfile │ └── kube │ ├── Makefile │ ├── deployment.yml │ ├── service.yml │ └── webthing-go.yml ├── go.mod ├── go.sum └── webthing.go /.dockerignore: -------------------------------------------------------------------------------- 1 | #.dockerignore 2 | Dockerfile 3 | .git/ 4 | # .gitignore 5 | *.tmp 6 | *~ 7 | a.out 8 | master 9 | 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # .gitignore 2 | *.tmp 3 | *~ 4 | a.out 5 | master 6 | simplest-thing 7 | *-webthing-go 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | -------------------------------------------------------------------------------- /.whitesource: -------------------------------------------------------------------------------- 1 | { 2 | "scanSettings": { 3 | "configMode": "AUTO", 4 | "configExternalURL": "" 5 | }, 6 | "checkRunSettings": { 7 | "vulnerableCheckRunConclusionLevel": "failure" 8 | }, 9 | "issueSettings": { 10 | "minSeverityLevel": "LOW" 11 | } 12 | } -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | #!/bin/echo docker build . -f 2 | # -*- coding: utf-8 -*- 3 | # SPDX-License-Identifier: MIT 4 | #{ 5 | # Copyright 2019-present Samsung Electronics France SAS, and other contributors 6 | # 7 | # This Source Code Form is subject to the terms of the MIT Licence 8 | # If a copy of the MIT was not distributed with this file 9 | # You can obtain one at: 10 | # https://spdx.org/licenses/MIT.html 11 | #} 12 | 13 | FROM golang:1.12.9-alpine3.10 AS webthing-go-builder 14 | LABEL maintainer "Philippe Coval (p.coval@samsung.com)" 15 | 16 | ENV project webthing-go 17 | ENV project_dir /usr/local/src/github.com/rzr/${project}/ 18 | 19 | RUN echo "#log: Setup system" \ 20 | && apk update \ 21 | && apk add make sudo \ 22 | && rm -rf /var/cache/apk/* \ 23 | && sync 24 | 25 | COPY Makefile ${project_dir} 26 | WORKDIR ${project_dir} 27 | RUN echo "#log: ${project}: Preparing sources" \ 28 | && set -x \ 29 | && make rule/setup/alpine \ 30 | && sync 31 | 32 | COPY . ${project_dir} 33 | RUN echo "#log: ${project}: Buidling sources" \ 34 | && set -x \ 35 | && make all \ 36 | && sync 37 | 38 | FROM alpine:3.10 39 | ENV project webthing-go 40 | ENV project_dir /usr/local/src/github.com/rzr/${project}/ 41 | COPY --from=webthing-go-builder ${project_dir}/simplest-webthing-go /usr/local/bin/ 42 | EXPOSE 8888 43 | ENTRYPOINT [ "/usr/local/bin/simplest-webthing-go" ] 44 | CMD [] 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. 374 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #! /usr/bin/make -f 2 | # -*- makefile -*- 3 | # ex: set tabstop=4 noexpandtab: 4 | # Copyright: 2019-present Samsung Electronics Co., Ltd. and other contributors 5 | # SPDX-License-Identifier: MPL-2.0 6 | 7 | default: all 8 | @echo "# log: $@: $^" 9 | 10 | package_name?=webthing-go 11 | port?=8888 12 | url?=http://localhost:${port} 13 | main_name?=simplest-webthing-go 14 | main_src?=example/${main_name}/simplest-thing.go 15 | main_srcs?=$(wildcard ./example/*/*.go | sort) 16 | main_dirs?=$(dir ${main_srcs}) 17 | sudo?=sudo 18 | go?=go 19 | 20 | 21 | all: get version build 22 | @echo "# log: $@: $^" 23 | 24 | get: 25 | ${go} $@ 26 | 27 | build: ${main_srcs} get 28 | ${go} $@ 29 | for app in ${main_dirs}; do ${go} $@ $${app} ; done 30 | 31 | devel/run: ${main_src} 32 | -${make} get 33 | ${go} run $< 34 | 35 | ${main_name}: build 36 | ldd $@ 37 | 38 | run: ${main_src} 39 | ${go} run $< 40 | 41 | start: ${main_name} 42 | ${ 94 | * 95 | * 96 | * 97 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # SPDX-License-Identifier: MIT 3 | #{ 4 | # Copyright 2019-present Samsung Electronics France SAS, and other contributors 5 | # 6 | # This Source Code Form is subject to the terms of the MIT Licence 7 | # If a copy of the MIT was not distributed with this file 8 | # You can obtain one at: 9 | # https://spdx.org/licenses/MIT.html 10 | #} 11 | 12 | version: "2" 13 | 14 | services: 15 | default: 16 | build: . 17 | ports: 18 | - "8888:8888" 19 | network_mode: "host" 20 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # WEBTHING-GO DOCS # 2 | 3 | ## INDEX: ## 4 | 5 | * [kube](kube) 6 | * [K3S](k3s) 7 | 8 | 9 | ## RESOURCES: ## 10 | 11 | * 12 | * 13 | -------------------------------------------------------------------------------- /docs/k3s.md: -------------------------------------------------------------------------------- 1 | # WEBTHING-GO WITH K3S # 2 | 3 | As an extra, here is a recipe to run a service using K3S: 4 | 5 | ```sh 6 | name="webthing-go" 7 | image="rzrfreefr/${name}:latest" 8 | kubectl="sudo kubectl" 9 | 10 | sudo sync 11 | curl -sfL "https://get.k3s.io" | sh - # v0.8.0 12 | sudo systemctl status k3s.service 13 | 14 | $kubectl get nodes # Wait "Ready state" 15 | #| {host} Ready master 51s v1.14.4-k3s.1 16 | 17 | $kubectl run --generator="run-pod/v1" "${name}" --image="${image}" 18 | 19 | $kubectl get all --all-namespaces | grep "$name" 20 | #| default pod/webthing-go 1/1 Running 0 19s 21 | #| default pod/webthing-go-688f84fc55-df8n4 1/1 Running 0 40s 22 | 23 | pod=$($kubectl get all --all-namespaces \ 24 | | grep -o "pod/${name}-.*" | cut -d/ -f2 | awk '{ print $1}' \ 25 | || echo failure) && echo pod="$pod" 26 | $kubectl describe pod "$pod" | grep 'Status: Running' 27 | ip=$($kubectl describe pod "$pod" | grep 'IP:' | awk '{ print $2 }') && echo "ip=${ip}" 28 | 29 | curl -I "http://${ip}:8888" | grep 'HTTP/1.1' 30 | 31 | sudo cat "/proc/$(pidof simplest-webthing-go | cut -d' ' -f1)/smaps" 32 | #| 00fc2000-00fe3000 rw-p 00000000 00:00 0 [heap] 33 | #| Size: 132 kB 34 | #| (...) 35 | #| 7fff1e838000-7fff1e859000 rw-p 00000000 00:00 0 [stack] 36 | #| Size: 132 kB 37 | #| (...) 38 | 39 | # Remove if needed 40 | /usr/local/bin/k3s-uninstall.sh 41 | ``` 42 | 43 | 44 | ## RESOURCES: ## 45 | 46 | * 47 | * 48 | * 49 | -------------------------------------------------------------------------------- /docs/kube.md: -------------------------------------------------------------------------------- 1 | # WEBTHING-GO WITH KUBERNETES: # 2 | 3 | ## SERVICE USING MINIKUBE: ### 4 | 5 | As an extra, here is a recipe to run a service using K8s's minikube: 6 | 7 | ```sh 8 | name="webthing-go" 9 | url="https://raw.githubusercontent.com/rzr/webthing-go/master/extra/tools/kube/$name.yml" 10 | kubectl=kubectl 11 | kubectl version || kubectl="sudo kubectl" # Maybe you'd better check your env 12 | 13 | minikube version 14 | #| minikube version: v1.3.0 15 | 16 | minikube start || minikube logs --alsologtostderr 17 | 18 | $kubectl version 19 | #| Client Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.1", ... 20 | #| Server Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.2", ... 21 | 22 | $kubectl apply -f "${url}" 23 | #| deployment.extensions/webthing-go created 24 | #| service/webthing-go created 25 | $kubectl get services 26 | #| webthing-go NodePort 10.100.249.206 8888:30080/TCP 4s 27 | 28 | minikube service ${name} --url 29 | #| http://192.168.99.102:30080 30 | time minikube service ${name} 31 | #| 🎉 Opening kubernetes service default/webthing-go in default browser... 32 | ``` 33 | 34 | 35 | ### CLUSTER USING KUBEADM: ### 36 | 37 | The process can be automatically move between cluster's nodes: 38 | 39 | ```sh 40 | project="webthing-go" 41 | kubectl=kubectl 42 | command="go run example/simplest-thing.go" 43 | 44 | kubectl get nodes 45 | #| NAME STATUS ROLES AGE VERSION 46 | #| slave01 Ready 94m v1.15.2 47 | #| master Ready master 99m v1.15.2 48 | 49 | kubectl describe nodes 50 | 51 | kubectl get services $project 52 | #| webthing-go NodePort 10.104.44.241 8888:30080/TCP 32s 53 | 54 | pod=$($kubectl get all --all-namespaces \ 55 | | grep -o "pod/${project}.*" | cut -d/ -f2 | awk '{ print $1}' \ 56 | || echo failure) && echo pod="$pod" 57 | 58 | kubectl describe pods "$pod" 59 | 60 | ip=$($kubectl describe pod "$pod" | grep 'IP:' | awk '{ print $2 }') && echo "ip=${ip}" 61 | 62 | curl -i http://$ip:8888/ | grep "HTTP/1.1 200 OK" 63 | 64 | #| webthing-go-58d7cc6657 1 1 1 34m 65 | 66 | # Move process to slave host 67 | kubectl drain $HOSTNAME --ignore-daemonsets --delete-local-data 68 | kubectl cordon $HOSTNAME 69 | kubectl uncordon $hostname 70 | $kubectl get all --all-namespaces | grep $project 71 | ps auxf | grep -5 "$command" | grep -v grep # on slave 72 | #| go run ... 73 | 74 | # Moving back to master host 75 | kubectl drain $hostname --ignore-daemonsets --delete-local-data 76 | kubectl cordon $hostname 77 | kubectl uncordon $HOSTNAME 78 | $kubectl get all --all-namespaces | grep $project 79 | ps auxf | grep -- "$command" | grep -v grep # on master 80 | #| root 1561 0.2 0.2 3474520 48392 ? Ssl 16:08 0:26 /usr/bin/containerd 81 | #| root 11758 0.0 0.0 107344 5428 ? Sl 19:33 0:00 \_ containerd-shim -namespace moby ... 82 | #| root 11779 0.0 0.0 5620 2320 ? Ss 19:33 0:00 | \_ /usr/bin/make start 83 | #| root 11798 0.1 0.1 1295752 19404 ? Sl 19:33 0:00 | \_ go run example/simplest-thing.go 84 | #| root 11924 0.0 0.0 477272 5696 ? Sl 19:33 0:00 | \_ /tmp/go-build000000403/b001/exe/simplest-thing 85 | ``` 86 | 87 | ## RESOURCES: ## 88 | 89 | * 90 | -------------------------------------------------------------------------------- /docs/microk8s.md: -------------------------------------------------------------------------------- 1 | # WEBTHING-GO WITH MICROK8S # 2 | 3 | As an extra, here is a recipe to run a service using Microk8s: 4 | 5 | ### SERVICE: ### 6 | 7 | ```sh 8 | name="webthing-go" 9 | url="https://raw.githubusercontent.com/rzr/${name}/master/extra/tools/kube/$name.yml" 10 | export PATH="/snap/microk8s/current/:/snap/bin/:$PATH" 11 | kubectl="microk8s.kubectl" 12 | port=8888 13 | # 14 | sudo sync 15 | sudo snap install microk8s --classic # v1.15.2 16 | 17 | microk8s.enable dns 18 | $kubectl apply -f "${url}" 19 | $kubectl describe services/$name 20 | $kubectl get all --all-namespaces | grep "$name" | grep 'Running' 21 | # Through kube-proxy 22 | port=$($kubectl get svc ${name} -o=jsonpath="{.spec.ports[?(@.port==$port)].nodePort}") 23 | curl -i http://127.0.0.1:${port}/ | grep 'HTTP/1.1' 24 | #| HTTP/1.1 200 OK 25 | 26 | # Remove if needed 27 | microk8s.reset 28 | $kubectl delete --all pod 29 | $kubectl delete --all node 30 | $kubectl delete --all services 31 | sudo snap remove microk8s 32 | ``` 33 | 34 | 35 | ### DEPLOYMENT: ### 36 | 37 | ```sh 38 | name="webthing-go" 39 | image="rzrfreefr/${name}:latest" 40 | export PATH=/snap/microk8s/current/:$PATH 41 | kubectl="kubectl" 42 | port=8888 43 | 44 | sudo sync 45 | sudo snap install microk8s --classic # v1.15.2 46 | 47 | sudo systemctl status | grep kube 48 | #| (...) 49 | #| /snap/microk8s/743/kube-apiserver 50 | #| (...) 51 | 52 | $kubectl cluster-info 53 | #| Kubernetes master is running at http://localhost:8080 54 | 55 | $kubectl get services 56 | #| NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 57 | #| kubernetes ClusterIP 10.152.183.1 443/TCP 15m 58 | 59 | $kubectl get nodes # Wait "Ready state" 60 | #| {host} Ready master 51s {version} 61 | 62 | microk8s.enable dns 63 | 64 | $kubectl run --generator=run-pod/v1 "${name}" --image="${image}" 65 | 66 | $kubectl get all --all-namespaces | grep "$name" # ContainerCreating, Running 67 | #| default pod/webthing-go 1/1 Running 0 19s 68 | 69 | pod=$($kubectl get all --all-namespaces \ 70 | | grep -o "pod/${name}-.*" | cut -d/ -f2 | awk '{ print $1}' \ 71 | || echo failure) && echo pod="$pod" 72 | $kubectl describe pod "$pod" | grep 'Status: * Running' 73 | ip=$($kubectl describe pod "$pod" | grep 'IP:' | awk '{ print $2 }') && echo "ip=${ip}" 74 | 75 | curl -qi "http://${ip}:${port}" | grep 'HTTP/1.1' 76 | #| HTTP/1.1 200 OK 77 | 78 | sudo cat "/proc/$(pidof simplest-webthing-go | cut -d' ' -f1)/smaps" | grep -2 ']' 79 | #| 00fc2000-00fe3000 rw-p 00000000 00:00 0 [heap] 80 | #| Size: 132 kB 81 | #| (...) 82 | #| 7fff1e838000-7fff1e859000 rw-p 00000000 00:00 0 [stack] 83 | #| Size: 132 kB 84 | #| (...) 85 | ``` 86 | 87 | ## RESOURCES: ## 88 | 89 | * 90 | * 91 | * 92 | -------------------------------------------------------------------------------- /example/simplest-webthing-go/simplest-thing.go: -------------------------------------------------------------------------------- 1 | // -*- Mode: Go; indent-tabs-mode: t -*- 2 | // Copyright: 2019-present Samsung Electronics Co., Ltd. and other contributors 3 | // SPDX-License-Identifier: MPL-2.0 4 | 5 | package main 6 | 7 | import ( 8 | webthing "github.com/rzr/webthing-go" 9 | "fmt" 10 | ) 11 | 12 | func valueHandler(update interface{}) { 13 | fmt.Println("change:", (update).(bool)) 14 | } 15 | 16 | func main() { 17 | thing := webthing.NewThing( 18 | "urn:dev:ops:my-actuator-1234", 19 | "ActuatorExample", 20 | []string{"OnOffSwitch"}, 21 | "An actuator example") 22 | 23 | onProperty := webthing.NewProperty("on", "boolean", false, valueHandler) 24 | thing.AddProperty(onProperty) 25 | 26 | server := webthing.NewServer(thing, 8888) 27 | server.Start() 28 | } 29 | -------------------------------------------------------------------------------- /example/single-webthing-go/single-thing.go: -------------------------------------------------------------------------------- 1 | // -*- Mode: Go; indent-tabs-mode: t -*- 2 | // Copyright: 2019-present Samsung Electronics Co., Ltd. and other contributors 3 | // SPDX-License-Identifier: MPL-2.0 4 | 5 | package main 6 | 7 | import ( 8 | webthing "github.com/rzr/webthing-go" 9 | ) 10 | 11 | func main() { 12 | thing := webthing.NewThing( 13 | "urn:dev:ops:my-lamp-1234", 14 | "My Lamp", 15 | []string{"OnOffSwitch", "Light"}, 16 | "A web connected lamp") 17 | 18 | onProperty := webthing.NewProperty("on", "boolean", false, nil) 19 | thing.AddProperty(onProperty) 20 | 21 | brightnessProperty := webthing.NewProperty("brightness", "integer", 0, nil) 22 | thing.AddProperty(brightnessProperty) 23 | 24 | server := webthing.NewServer(thing, 8888) 25 | server.Start() 26 | } 27 | -------------------------------------------------------------------------------- /extra/tools/docker/debian/Dockerfile: -------------------------------------------------------------------------------- 1 | #!/bin/echo docker build . -f 2 | # -*- coding: utf-8 -*- 3 | # SPDX-License-Identifier: MIT 4 | #{ 5 | # Copyright 2019-present Samsung Electronics France SAS, and other contributors 6 | # 7 | # This Source Code Form is subject to the terms of the MIT Licence 8 | # If a copy of the MIT was not distributed with this file 9 | # You can obtain one at: 10 | # https://spdx.org/licenses/MIT.html 11 | #} 12 | 13 | FROM golang:1.12.9 as webthing-go-builder 14 | MAINTAINER Philippe Coval (p.coval@samsung.com) 15 | 16 | ENV DEBIAN_FRONTEND noninteractive 17 | ENV LC_ALL en_US.UTF-8 18 | ENV LANG ${LC_ALL} 19 | 20 | RUN echo "#log: Configuring locales" \ 21 | && set -x \ 22 | && apt-get update -y \ 23 | && apt-get install -y locales \ 24 | && echo "${LC_ALL} UTF-8" | tee /etc/locale.gen \ 25 | && locale-gen ${LC_ALL} \ 26 | && dpkg-reconfigure locales \ 27 | && sync 28 | 29 | ENV project webthing-go 30 | ENV project_dir /go/src/github.com/rzr/${project}/ 31 | ADD Makefile ${project_dir} 32 | WORKDIR ${project_dir} 33 | RUN echo "#log: Setup system" \ 34 | && apt-get update -y \ 35 | && apt-get install -y make sudo \ 36 | && apt-get clean \ 37 | && sync 38 | 39 | ADD . ${project_dir} 40 | WORKDIR ${project_dir} 41 | RUN echo "#log: ${project}: Preparing sources" \ 42 | && set -x \ 43 | && make all \ 44 | && sync 45 | 46 | FROM debian:10 47 | ENV project webthing-go 48 | ENV project_dir /go/src/github.com/rzr/${project}/ 49 | COPY --from=webthing-go-builder ${project_dir}/simplest-webthing-go /usr/local/bin/ 50 | EXPOSE 8888 51 | ENTRYPOINT [ "/usr/local/bin/simplest-webthing-go" ] 52 | CMD [] 53 | -------------------------------------------------------------------------------- /extra/tools/kube/Makefile: -------------------------------------------------------------------------------- 1 | #! /usr/bin/make -f 2 | # -*- makefile -*- 3 | # ex: set tabstop=4 noexpandtab: 4 | # Copyright: 2019-present Samsung Electronics Co., Ltd. and other contributors 5 | # SPDX-License-Identifier: MPL-2.0 6 | 7 | name?=webthing-go 8 | 9 | ${name}.yml: deployment.yml service.yml Makefile 10 | @echo '#YAML' > $@ 11 | @echo '---' >> $@ 12 | cat deployment.yml >> $@ 13 | @echo '---' >> $@ 14 | cat service.yml >> $@ 15 | @echo '---' >> $@ 16 | -------------------------------------------------------------------------------- /extra/tools/kube/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Deployment 3 | metadata: 4 | name: webthing-go 5 | spec: 6 | replicas: 1 7 | template: 8 | metadata: 9 | labels: 10 | run: webthing-go 11 | spec: 12 | containers: 13 | - image: rzrfreefr/webthing-go:latest 14 | name: webthing-go 15 | ports: 16 | - containerPort: 8888 17 | -------------------------------------------------------------------------------- /extra/tools/kube/service.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: webthing-go 5 | spec: 6 | ports: 7 | - nodePort: 30080 8 | port: 8888 9 | protocol: TCP 10 | targetPort: 8888 11 | selector: 12 | run: webthing-go 13 | sessionAffinity: None 14 | type: NodePort 15 | status: 16 | loadBalancer: {} 17 | -------------------------------------------------------------------------------- /extra/tools/kube/webthing-go.yml: -------------------------------------------------------------------------------- 1 | #YAML 2 | --- 3 | apiVersion: extensions/v1beta1 4 | kind: Deployment 5 | metadata: 6 | name: webthing-go 7 | spec: 8 | replicas: 1 9 | template: 10 | metadata: 11 | labels: 12 | run: webthing-go 13 | spec: 14 | containers: 15 | - image: rzrfreefr/webthing-go:latest 16 | name: webthing-go 17 | ports: 18 | - containerPort: 8888 19 | --- 20 | apiVersion: v1 21 | kind: Service 22 | metadata: 23 | name: webthing-go 24 | spec: 25 | ports: 26 | - nodePort: 30080 27 | port: 8888 28 | protocol: TCP 29 | targetPort: 8888 30 | selector: 31 | run: webthing-go 32 | sessionAffinity: None 33 | type: NodePort 34 | status: 35 | loadBalancer: {} 36 | --- 37 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/rzr/webthing-go 2 | 3 | go 1.12 4 | 5 | require github.com/julienschmidt/httprouter v1.2.0 6 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g= 2 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 3 | -------------------------------------------------------------------------------- /webthing.go: -------------------------------------------------------------------------------- 1 | // -*- Mode: Go; indent-tabs-mode: t -*- 2 | // Copyright: 2019-present Samsung Electronics Co., Ltd. and other contributors 3 | // SPDX-License-Identifier: MPL-2.0 4 | 5 | package webthing 6 | 7 | import ( 8 | "encoding/json" 9 | "fmt" 10 | "github.com/julienschmidt/httprouter" 11 | "io" 12 | "net/http" 13 | ) 14 | 15 | // Value is a multitypes placeholder, only one is used 16 | type Value struct { 17 | boolean bool 18 | integer int 19 | number float64 20 | string string 21 | } 22 | 23 | // Property is made of value(s) 24 | type Property struct { 25 | name string 26 | valuetype string 27 | value *Value 28 | handler func(interface{}) 29 | } 30 | 31 | func (property Property) setValue(value interface{}) { 32 | switch property.valuetype { 33 | case "boolean": 34 | property.value.boolean = (value).(bool) 35 | case "integer": 36 | property.value.integer = (value).(int) 37 | case "number": 38 | property.value.number = (value).(float64) 39 | case "string": 40 | property.value.string = (value).(string) 41 | } 42 | if property.handler != nil { 43 | property.handler(value) 44 | } 45 | } 46 | 47 | func (property Property) getValue() interface{} { 48 | switch property.valuetype { 49 | case "boolean": 50 | return property.value.boolean 51 | case "integer": 52 | return property.value.integer 53 | case "number": 54 | return property.value.number 55 | case "string": 56 | return property.value.string 57 | } 58 | return nil 59 | } 60 | 61 | // NewProperty contructs and assign value 62 | func NewProperty(name string, valuetype string, value interface{}, handler func(interface{})) *Property { 63 | var property = Property{name: name, valuetype: valuetype, handler: handler} 64 | property.value = &Value{} 65 | property.setValue(value) 66 | return &property 67 | } 68 | 69 | // Thing is made of Property(ies) 70 | type Thing struct { 71 | id string 72 | title string 73 | context string 74 | types []string 75 | description string 76 | properties map[string]Property 77 | href string 78 | } 79 | 80 | // AddProperty adds property (along values) to thing 81 | func (thing Thing) AddProperty(property *Property) { 82 | thing.properties[property.name] = *property 83 | } 84 | 85 | func (thing Thing) getPropertiesDescriptions() map[string]interface{} { 86 | result := make(map[string]interface{}) 87 | 88 | for name, property := range thing.properties { 89 | description := make(map[string]interface{}) 90 | description["type"] = property.valuetype 91 | description["href"] = thing.href + "properties/" + name 92 | result[name] = description 93 | } 94 | return result 95 | } 96 | 97 | // NewThing construct without properties 98 | func NewThing(id string, title string, types []string, description string) *Thing { 99 | thing := Thing{ 100 | id: id, 101 | title: title, 102 | href: "/", 103 | properties: make(map[string]Property), 104 | types: types, 105 | description: description, 106 | context: "https://iot.mozilla.org/schemas"} 107 | if thing.types == nil { 108 | thing.types = make([]string, 0) 109 | } 110 | return &thing 111 | } 112 | 113 | // Server is an HTTP server made for webthings model 114 | type Server struct { 115 | thing *Thing 116 | port int 117 | } 118 | 119 | func (server Server) thingHandler(w http.ResponseWriter, req *http.Request, _ httprouter.Params) { 120 | description := make(map[string]interface{}) 121 | description["id"] = server.thing.id 122 | description["title"] = server.thing.title 123 | description["@context"] = server.thing.context 124 | description["@type"] = server.thing.types 125 | description["properties"] = server.thing.getPropertiesDescriptions() 126 | description["events"] = make(map[string]interface{}) 127 | description["links"] = [...]map[string]interface{}{ 128 | {"rel": "properties", "href": "/properties"}} 129 | description["description"] = server.thing.description 130 | description["actions"] = make(map[string]interface{}) 131 | 132 | description["href"] = server.thing.href 133 | 134 | // https://github.com/golang/go/issues/28940 135 | scheme := "http" 136 | if req.TLS != nil { 137 | scheme = "https" 138 | } 139 | description["base"] = scheme + "://" + req.Host + req.URL.RequestURI() 140 | 141 | description["security"] = "nosec_sc" 142 | description["securityDefinitions"] = make(map[string]interface{}) 143 | description["securityDefinitions"].(map[string]interface{})["nosec_sc"] = 144 | map[string]interface{}{"scheme": "nosec"} 145 | 146 | var body, _ = json.Marshal(description) 147 | io.WriteString(w, string(body)) 148 | } 149 | 150 | func (server Server) propertiesHandler(w http.ResponseWriter, req *http.Request, _ httprouter.Params) { 151 | description := make(map[string]interface{}) 152 | for name, property := range server.thing.properties { 153 | description[name] = property.getValue() 154 | } 155 | var body, _ = json.Marshal(description) 156 | io.WriteString(w, string(body)) 157 | 158 | } 159 | 160 | func (server Server) propertyPutHandler(w http.ResponseWriter, req *http.Request, params httprouter.Params) { 161 | decoder := json.NewDecoder(req.Body) 162 | object := make(map[string]interface{}) 163 | err := decoder.Decode(&object) 164 | if err != nil { 165 | fmt.Println(err) 166 | } 167 | name := params.ByName("propertyName") 168 | property := server.thing.properties[name] 169 | property.setValue(object[name]) 170 | var body, _ = json.Marshal(object) 171 | io.WriteString(w, string(body)) 172 | } 173 | 174 | func (server Server) propertyGetHandler(w http.ResponseWriter, req *http.Request, params httprouter.Params) { 175 | name := params.ByName("propertyName") 176 | property := server.thing.properties[name] 177 | object := make(map[string]interface{}) 178 | object[name] = property.getValue() 179 | var body, _ = json.Marshal(object) 180 | io.WriteString(w, string(body)) 181 | } 182 | 183 | // NewServer constructs an http server to be started 184 | func NewServer(thing *Thing, port int) *Server { 185 | return &Server{thing: thing, port: port} 186 | } 187 | 188 | // Start listening for incoming requests and process using handlers 189 | func (server Server) Start() { 190 | router := httprouter.New() 191 | router.GET("/", server.thingHandler) 192 | router.GET("/properties", server.propertiesHandler) 193 | router.GET("/properties/:propertyName", server.propertyGetHandler) 194 | router.PUT("/properties/:propertyName", server.propertyPutHandler) 195 | 196 | address := fmt.Sprintf(":%d", server.port) 197 | fmt.Print("Listening: ") 198 | fmt.Println(address) 199 | 200 | err := http.ListenAndServe(address, router) 201 | fmt.Println(err) 202 | } 203 | --------------------------------------------------------------------------------