├── .gitignore ├── .idea └── markdown-navigator.xml ├── .travis.yml ├── LICENSE ├── README.md ├── configuration ├── doc.go ├── ini.go └── ini_test.go ├── cryptographic ├── aes_decrypt.go ├── aes_decrypt_test.go ├── aes_encrypt.go ├── aes_encrypt_test.go └── doc.go ├── data ├── configuration │ ├── grafana.ini │ └── test.toml └── cryptographic │ └── APT.yar.aes ├── database ├── doc.go ├── mssql.go ├── mssql_test.go ├── mysql.go └── mysql_test.go ├── doc.go ├── docker ├── doc.go ├── docker.go └── docker_test.go ├── email ├── doc.go ├── gomail.go └── gomail_test.go ├── firewall ├── iptables.go └── iptables_test.go ├── flag └── doc.go ├── go.mod ├── go.sum ├── grafana └── doc.go ├── http ├── doc.go ├── http.go ├── http_test.go ├── wget.go └── wget_test.go ├── log └── doc.go ├── nosql ├── doc.go ├── mongo.go ├── mongo_test.go ├── redis.go └── redis_test.go ├── rabbitmq ├── doc.go ├── rabbitmq.go └── rabbitmq_test.go ├── ssh ├── auth.go ├── client.go ├── configurer.go ├── doc.go ├── protocol.go ├── ssh.go └── ssh_test.go ├── tickstack ├── doc.go ├── influxdb.go ├── influxdb_test.go ├── kapacitor.go └── kapacitor_test.go └── utils ├── doc.go ├── path_walk.go └── path_walk_test.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Go template 3 | # Binaries for programs and plugins 4 | *.exe 5 | *.exe~ 6 | *.dll 7 | *.so 8 | *.dylib 9 | 10 | # Test binary, build with `go test -c` 11 | *.test 12 | 13 | # Output of the go coverage tool, specifically when used with LiteIDE 14 | *.out 15 | 16 | /.idea 17 | 18 | -------------------------------------------------------------------------------- /.idea/markdown-navigator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 36 | 37 | 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 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - 1.13.3 4 | - tip 5 | 6 | sudo: false 7 | 8 | before_install: 9 | - go get github.com/mattn/goveralls 10 | 11 | install: true 12 | 13 | script: 14 | - env GO111MODULES=on go build 15 | - env GO111MODULES=on go test 16 | 17 | after_success: 18 | - goveralls -service=travis-ci 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | {one line to give the program's name and a brief idea of what it does.} 635 | Copyright (C) {year} {name of author} 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | {project} Copyright (C) {year} {fullname} 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![minimum golang 1.13](https://img.shields.io/badge/golang-1.13%2B-orange.svg) 2 | [![Go Report Card](https://goreportcard.com/badge/github.com/crazy-canux/go-devops)](https://goreportcard.com/report/github.com/crazy-canux/go-devops) 3 | [![Go.dev](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/github.com/crazy-canux/go-devops) 4 | [![Build Status](https://travis-ci.org/crazy-canux/go-devops.svg?branch=master)](https://travis-ci.org/crazy-canux/go-devops) 5 | [![Coverage Status](https://coveralls.io/repos/github/crazy-canux/go-devops/badge.svg?branch=master)](https://coveralls.io/github/crazy-canux/go-devops?branch=master) 6 | 7 | # go-devops 8 | 9 | tons of devops related tools. -------------------------------------------------------------------------------- /configuration/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | INI 3 | 4 | TOML 5 | 6 | https://github.com/BurntSushi/toml 7 | 8 | "github.com/BurntSushi/toml" 9 | 10 | YAML 11 | 12 | https://github.com/go-yaml/yaml 13 | 14 | "gopkg.in/yaml.v2" 15 | 16 | */ 17 | package configuration 18 | -------------------------------------------------------------------------------- /configuration/ini.go: -------------------------------------------------------------------------------- 1 | package configuration 2 | 3 | import ( 4 | "github.com/go-ini/ini" 5 | "log" 6 | ) 7 | 8 | func LoadIni(filename string) (*ini.File, error) { 9 | cfg, err := ini.Load(filename) 10 | if err != nil { 11 | log.Printf("Load %s failed.", filename) 12 | return &ini.File{}, err 13 | } 14 | return cfg, nil 15 | } 16 | 17 | func GetKey(cfg *ini.File, section, key string) (*ini.Key, error) { 18 | sec, err := cfg.GetSection(section) 19 | if err != nil { 20 | log.Printf("Section %s not exist.", section) 21 | return &ini.Key{}, err 22 | } 23 | k, err := sec.GetKey(key) 24 | if err != nil { 25 | log.Printf("Key %s not exist.", key) 26 | return &ini.Key{}, err 27 | } 28 | return k, nil 29 | } 30 | 31 | func SetKey(cfg *ini.File, section, key, value string, create bool) error { 32 | sec, err := cfg.GetSection(section) 33 | if err != nil { 34 | log.Printf("Section %s not exist.", section) 35 | return nil 36 | } 37 | k, err := sec.GetKey(key) 38 | if err != nil && !create { 39 | log.Printf("Key %s not exist.", key) 40 | return err 41 | } else if err != nil && create { 42 | log.Println("Add new key.") 43 | _, err = sec.NewKey(key, value) 44 | if err != nil { 45 | log.Printf("Create new key %s failed.", key) 46 | return nil 47 | } 48 | } else { 49 | k.SetValue(value) 50 | } 51 | return nil 52 | } 53 | -------------------------------------------------------------------------------- /configuration/ini_test.go: -------------------------------------------------------------------------------- 1 | package configuration 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | var filename = "/home/canux/Src/go/src/github.com/crazy-canux/go-devops/data/configuration/grafana.ini" 8 | 9 | func TestGetKey(t *testing.T) { 10 | cfg, err := LoadIni(filename) 11 | if err != nil { 12 | t.Errorf("load file error: %v", err) 13 | } 14 | appMode, err := GetKey(cfg, "", "app_mode") 15 | if err != nil { 16 | t.Errorf("get key error: %v", err) 17 | } 18 | if appMode.String() != "production" { 19 | t.Log(appMode) 20 | } 21 | } 22 | 23 | func TestSetKey(t *testing.T) { 24 | cfg, err := LoadIni(filename) 25 | if err != nil { 26 | t.Errorf("load file error: %v", err) 27 | } 28 | err = SetKey(cfg, "auth.anonymous", "enabled", "true", true) 29 | if err != nil { 30 | t.Errorf("set key error: %v", err) 31 | } 32 | if err := cfg.SaveTo(filename); err != nil { 33 | t.Errorf("save file error: %v", err) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /cryptographic/aes_decrypt.go: -------------------------------------------------------------------------------- 1 | package cryptographic 2 | 3 | import ( 4 | "crypto/aes" 5 | "crypto/cipher" 6 | "errors" 7 | "io/ioutil" 8 | "log" 9 | //"fmt" 10 | //"encoding/hex" 11 | ) 12 | 13 | // decrypt file with aes and save to another file. 14 | func DecryptFile(src, dest, key string) error { 15 | 16 | cipherText, err := ioutil.ReadFile(src) 17 | if err != nil { 18 | log.Println("Read file failed.") 19 | return err 20 | } 21 | 22 | block, err := aes.NewCipher([]byte(key)) 23 | if err != nil { 24 | log.Println("Create cipher block failed.") 25 | return err 26 | } 27 | 28 | if len(cipherText) < aes.BlockSize { 29 | log.Println("Key must be 16,24,32.") 30 | return errors.New("ciphertext too short") 31 | } 32 | 33 | iv := cipherText[:aes.BlockSize] 34 | cipherText = cipherText[aes.BlockSize:] 35 | cipher.NewCFBDecrypter(block, iv).XORKeyStream(cipherText, cipherText) 36 | 37 | err = ioutil.WriteFile(dest, cipherText, 0755) 38 | if err != nil { 39 | log.Println("Save decrypted file failed.") 40 | return err 41 | } 42 | return nil 43 | } 44 | -------------------------------------------------------------------------------- /cryptographic/aes_decrypt_test.go: -------------------------------------------------------------------------------- 1 | package cryptographic 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | var src = "/home/canux/Src/go/src/github.com/crazy-canux/go-devops/data/cryptographic/APT.yar" 8 | var dest = "/home/canux/Src/go/src/github.com/crazy-canux/go-devops/data/cryptographic/APT.yar.aes" 9 | var verify = "/home/canux/Src/go/src/github.com/crazy-canux/go-devops/data/cryptographic/APT1.yar" 10 | 11 | // 16, 24, 32 12 | var key = "aNFX2EerZneJfG2z" 13 | 14 | func TestAesDecryptFile(t *testing.T) { 15 | err := DecryptFile(dest, verify, key) 16 | if err != nil { 17 | t.Error("Decrypt file failed.") 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /cryptographic/aes_encrypt.go: -------------------------------------------------------------------------------- 1 | package cryptographic 2 | 3 | import ( 4 | "crypto/aes" 5 | "crypto/cipher" 6 | "crypto/rand" 7 | "io" 8 | "io/ioutil" 9 | "log" 10 | ) 11 | 12 | // encrypt file with aes and save to another file. 13 | func EncryptFile(src, dest, key string) error { 14 | plaintext, err := ioutil.ReadFile(src) 15 | if err != nil { 16 | log.Println("Read file failed.") 17 | return err 18 | } 19 | 20 | block, err := aes.NewCipher([]byte(key)) 21 | if err != nil { 22 | log.Println("Create cipher block failed.") 23 | return err 24 | } 25 | 26 | cipherText := make([]byte, aes.BlockSize+len(plaintext)) 27 | iv := cipherText[:aes.BlockSize] 28 | if _, err := io.ReadFull(rand.Reader, iv); err != nil { 29 | log.Println("Read rand failed.") 30 | return err 31 | } 32 | 33 | cipher.NewCFBEncrypter(block, iv).XORKeyStream(cipherText[aes.BlockSize:], []byte(plaintext)) 34 | 35 | err = ioutil.WriteFile(dest, cipherText, 0755) 36 | if err != nil { 37 | log.Println("Save encrypted file failed.") 38 | return err 39 | } 40 | return nil 41 | } 42 | -------------------------------------------------------------------------------- /cryptographic/aes_encrypt_test.go: -------------------------------------------------------------------------------- 1 | package cryptographic 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | var src = "/home/canux/Src/go/src/github.com/crazy-canux/go-devops/data/cryptographic/APT.yar" 8 | var dest = "/home/canux/Src/go/src/github.com/crazy-canux/go-devops/data/cryptographic/APT.yar.aes" 9 | var verify = "/home/canux/Src/go/src/github.com/crazy-canux/go-devops/data/cryptographic/APT1.yar" 10 | 11 | // 16, 24, 32 12 | var key = "aNFX2EerZneJfG2z" 13 | 14 | func TestAesEncryptFile(t *testing.T) { 15 | 16 | err := EncryptFile(src, dest, key) 17 | if err != nil { 18 | t.Errorf("Encrypt file failed: %s", err) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /cryptographic/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | AES 3 | */ 4 | package cryptographic 5 | -------------------------------------------------------------------------------- /data/configuration/grafana.ini: -------------------------------------------------------------------------------- 1 | # #################### Grafana Configuration Example ##################### 2 | # 3 | # Everything has defaults so you only need to uncomment things you want to 4 | # change 5 | # possible values : production, development 6 | app_mode = production 7 | 8 | # instance name, defaults to HOSTNAME environment variable value or hostname if HOSTNAME var is empty 9 | ; instance_name = ${HOSTNAME} 10 | # ################################### Paths #################################### 11 | [paths] 12 | 13 | # Path to where grafana can store temp files, sessions, and the sqlite3 db (if that is used) 14 | ; data = /var/lib/grafana 15 | # Directory where grafana can store logs 16 | ; logs = /var/log/grafana 17 | # Directory where grafana will automatically scan and look for plugins 18 | ; plugins = /var/lib/grafana/plugins 19 | # folder that contains provisioning config files that grafana will apply on startup and while running. 20 | ; provisioning = conf/provisioning 21 | # ################################### Server #################################### 22 | [server] 23 | 24 | # Protocol (http, https, socket) 25 | ; protocol = http 26 | # The ip address to bind to, empty will bind to all interfaces 27 | ; http_addr = 28 | # The http port to use 29 | ; http_port = 3000 30 | # The public facing domain name used to access grafana from a browser 31 | ; domain = localhost 32 | # Redirect to correct domain if host header does not match domain 33 | # Prevents DNS rebinding attacks 34 | ; enforce_domain = false 35 | # The full public facing url you use in browser, used for redirects and emails 36 | # If you use reverse proxy and sub path specify full url (with sub path) 37 | ; root_url = http://localhost:3000 38 | # Log web requests 39 | ; router_logging = false 40 | # the path relative working path 41 | ; static_root_path = public 42 | # enable gzip 43 | ; enable_gzip = false 44 | # https certs & key file 45 | ; cert_file = 46 | ; cert_key = 47 | # Unix socket path 48 | ; socket = 49 | # ################################### Database #################################### 50 | [database] 51 | # You can configure the database connection by specifying type, host, name, user and password 52 | # as seperate properties or as on string using the url propertie. 53 | # Either "mysql", "postgres" or "sqlite3", it's your choice 54 | ; type = sqlite3 55 | ; host = 127.0.0.1:3306 56 | ; name = grafana 57 | ; user = root 58 | # If the password contains # or ; you have to wrap it with triple quotes. Ex """#password;""" 59 | ; password = 60 | # Use either URL or the previous fields to configure the database 61 | # Example: mysql://user:secret@host:port/database 62 | ; url = 63 | # For "postgres" only, either "disable", "require" or "verify-full" 64 | ; ssl_mode = disable 65 | # For "sqlite3" only, path relative to data_path setting 66 | ; path = grafana.db 67 | # Max idle conn setting default is 2 68 | ; max_idle_conn = 2 69 | # Max conn setting default is 0 (mean not set) 70 | ; max_open_conn = 71 | # Connection Max Lifetime default is 14400 (means 14400 seconds or 4 hours) 72 | ; conn_max_lifetime = 14400 73 | # Set to true to log the sql calls and execution times. 74 | log_queries = 75 | 76 | # ################################### Session #################################### 77 | [session] 78 | 79 | # Either "memory", "file", "redis", "mysql", "postgres", default is "file" 80 | ; provider = file 81 | # Provider config options 82 | # memory: not have any config yet 83 | # file: session dir path, is relative to grafana data_path 84 | # redis: config like redis server e.g. `addr=127.0.0.1:6379,pool_size=100,db=grafana` 85 | # mysql: go-sql-driver/mysql dsn config string, e.g. `user:password@tcp(127.0.0.1:3306)/database_name` 86 | # postgres: user=a password=b host=localhost port=5432 dbname=c sslmode=disable 87 | ; provider_config = sessions 88 | # Session cookie name 89 | ; cookie_name = grafana_sess 90 | # If you use session in https only, default is false 91 | ; cookie_secure = false 92 | # Session life time, default is 86400 93 | ; session_life_time = 86400 94 | # ################################### Data proxy ########################### 95 | [dataproxy] 96 | 97 | # This enables data proxy logging, default is false 98 | ; logging = false 99 | # ################################### Analytics #################################### 100 | [analytics] 101 | 102 | # Server reporting, sends usage counters to stats.grafana.org every 24 hours. 103 | # No ip addresses are being tracked, only simple counters to track 104 | # running instances, dashboard and error counts. It is very helpful to us. 105 | # Change this option to false to disable reporting. 106 | ; reporting_enabled = true 107 | # Set to false to disable all checks to https://grafana.net 108 | # for new vesions (grafana itself and plugins), check is used 109 | # in some UI views to notify that grafana or plugin update exists 110 | # This option does not cause any auto updates, nor send any information 111 | # only a GET request to http://grafana.com to get latest versions 112 | ; check_for_updates = true 113 | # Google Analytics universal tracking code, only enabled if you specify an id here 114 | ; google_analytics_ua_id = 115 | # ################################### Security #################################### 116 | [security] 117 | 118 | # default admin user, created on startup 119 | ; admin_user = admin 120 | # default admin password, can be changed before first start of grafana, or in profile settings 121 | ; admin_password = admin 122 | # used for signing 123 | ; secret_key = SW2YcwTIb9zpOOhoPsMm 124 | # Auto-login remember days 125 | ; login_remember_days = 7 126 | ; cookie_username = grafana_user 127 | ; cookie_remember_name = grafana_remember 128 | # disable gravatar profile images 129 | ; disable_gravatar = false 130 | # data source proxy whitelist (ip_or_domain:port separated by spaces) 131 | ; data_source_proxy_whitelist = 132 | # disable protection against brute force login attempts 133 | ; disable_brute_force_login_protection = false 134 | # ################################### Snapshots ########################### 135 | [snapshots] 136 | 137 | # snapshot sharing options 138 | ; external_enabled = true 139 | ; external_snapshot_url = https://snapshots-origin.raintank.io 140 | ; external_snapshot_name = Publish to snapshot.raintank.io 141 | # remove expired snapshot 142 | ; snapshot_remove_expired = true 143 | # ################################### Dashboards History ################## 144 | [dashboards] 145 | 146 | # Number dashboard versions to keep (per dashboard). Default: 20, Minimum: 1 147 | ; versions_to_keep = 20 148 | # ################################### Users ############################### 149 | [users] 150 | # disable user signup / registration 151 | ; allow_sign_up = true 152 | # Allow non admin users to create organizations 153 | ; allow_org_create = true 154 | # Set to true to automatically assign new users to the default organization (id 1) 155 | ; auto_assign_org = true 156 | # Default role new users will be automatically assigned (if disabled above is set to true) 157 | ; auto_assign_org_role = Viewer 158 | # Background text for the user field on the login page 159 | ; login_hint = email or username 160 | # Default UI theme ("dark" or "light") 161 | default_theme = light 162 | 163 | # External user management, these options affect the organization users view 164 | ; external_manage_link_url = 165 | ; external_manage_link_name = 166 | ; external_manage_info = 167 | # Viewers can edit/inspect dashboard settings in the browser. But not save the dashboard. 168 | ; viewers_can_edit = false 169 | [auth] 170 | 171 | # Set to true to disable (hide) the login form, useful if you use OAuth, defaults to false 172 | ; disable_login_form = false 173 | # Set to true to disable the signout link in the side menu. useful if you use auth.proxy, defaults to false 174 | ; disable_signout_menu = false 175 | # ################################### Anonymous Auth ########################## 176 | [auth.anonymous] 177 | enabled = true 178 | 179 | # enable anonymous access 180 | ; enabled = false 181 | # specify organization name that should be used for unauthenticated users 182 | ; org_name = Main Org. 183 | # specify role for unauthenticated users 184 | ; org_role = Viewer 185 | # ################################### Github Auth ########################## 186 | [auth.github] 187 | 188 | ; enabled = false 189 | ; allow_sign_up = true 190 | ; client_id = some_id 191 | ; client_secret = some_secret 192 | ; scopes = user:email,read:org 193 | ; auth_url = https://github.com/login/oauth/authorize 194 | ; token_url = https://github.com/login/oauth/access_token 195 | ; api_url = https://api.github.com/user 196 | ; team_ids = 197 | ; allowed_organizations = 198 | # ################################### Google Auth ########################## 199 | [auth.google] 200 | 201 | ; enabled = false 202 | ; allow_sign_up = true 203 | ; client_id = some_client_id 204 | ; client_secret = some_client_secret 205 | ; scopes = https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email 206 | ; auth_url = https://accounts.google.com/o/oauth2/auth 207 | ; token_url = https://accounts.google.com/o/oauth2/token 208 | ; api_url = https://www.googleapis.com/oauth2/v1/userinfo 209 | ; allowed_domains = 210 | # ################################### Generic OAuth ########################## 211 | [auth.generic_oauth] 212 | 213 | ; enabled = false 214 | ; name = OAuth 215 | ; allow_sign_up = true 216 | ; client_id = some_id 217 | ; client_secret = some_secret 218 | ; scopes = user:email,read:org 219 | ; auth_url = https://foo.bar/login/oauth/authorize 220 | ; token_url = https://foo.bar/login/oauth/access_token 221 | ; api_url = https://foo.bar/user 222 | ; team_ids = 223 | ; allowed_organizations = 224 | # ################################### Grafana.com Auth #################### 225 | [auth.grafana_com] 226 | 227 | ; enabled = false 228 | ; allow_sign_up = true 229 | ; client_id = some_id 230 | ; client_secret = some_secret 231 | ; scopes = user:email 232 | ; allowed_organizations = 233 | # ################################### Auth Proxy ########################## 234 | [auth.proxy] 235 | 236 | ; enabled = false 237 | ; header_name = X-WEBAUTH-USER 238 | ; header_property = username 239 | ; auto_sign_up = true 240 | ; ldap_sync_ttl = 60 241 | ; whitelist = 192.168.1.1, 192.168.2.1 242 | # ################################### Basic Auth ########################## 243 | [auth.basic] 244 | 245 | ; enabled = true 246 | # ################################### Auth LDAP ########################## 247 | [auth.ldap] 248 | 249 | ; enabled = false 250 | ; config_file = /etc/grafana/ldap.toml 251 | ; allow_sign_up = true 252 | # ################################### SMTP / Emailing ########################## 253 | [smtp] 254 | 255 | ; enabled = false 256 | ; host = localhost:25 257 | ; user = 258 | # If the password contains # or ; you have to wrap it with trippel quotes. Ex """#password;""" 259 | ; password = 260 | ; cert_file = 261 | ; key_file = 262 | ; skip_verify = false 263 | ; from_address = admin@grafana.localhost 264 | ; from_name = Grafana 265 | # EHLO identity in SMTP dialog (defaults to instance_name) 266 | ; ehlo_identity = dashboard.example.com 267 | [emails] 268 | 269 | ; welcome_email_on_sign_up = false 270 | # ################################### Logging ########################## 271 | [log] 272 | 273 | # Either "console", "file", "syslog". Default is console and file 274 | # Use space to separate multiple modes, e.g. "console file" 275 | ; mode = console file 276 | # Either "debug", "info", "warn", "error", "critical", default is "info" 277 | ; level = info 278 | # optional settings to set different levels for specific loggers. Ex filters = sqlstore:debug 279 | ; filters = 280 | # For "console" mode only 281 | [log.console] 282 | 283 | ; level = 284 | # log line format, valid options are text, console and json 285 | ; format = console 286 | # For "file" mode only 287 | [log.file] 288 | 289 | ; level = 290 | # log line format, valid options are text, console and json 291 | ; format = text 292 | # This enables automated log rotate(switch of following options), default is true 293 | ; log_rotate = true 294 | # Max line number of single file, default is 1000000 295 | ; max_lines = 1000000 296 | # Max size shift of single file, default is 28 means 1 << 28, 256MB 297 | ; max_size_shift = 28 298 | # Segment log daily, default is true 299 | ; daily_rotate = true 300 | # Expired days of log file(delete after max days), default is 7 301 | ; max_days = 7 302 | [log.syslog] 303 | 304 | ; level = 305 | # log line format, valid options are text, console and json 306 | ; format = text 307 | # Syslog network type and address. This can be udp, tcp, or unix. If left blank, the default unix endpoints will be used. 308 | ; network = 309 | ; address = 310 | # Syslog facility. user, daemon and local0 through local7 are valid. 311 | ; facility = 312 | # Syslog tag. By default, the process' argv[0] is used. 313 | ; tag = 314 | # ################################### Alerting ############################ 315 | [alerting] 316 | 317 | # Disable alerting engine & UI features 318 | ; enabled = true 319 | # Makes it possible to turn off alert rule execution but alerting UI is visible 320 | ; execute_alerts = true 321 | # ################################### Internal Grafana Metrics ########################## 322 | # Metrics available at HTTP API Url /metrics 323 | [metrics] 324 | 325 | # Disable / Enable internal metrics 326 | ; enabled = true 327 | # Publish interval 328 | ; interval_seconds = 10 329 | # Send internal metrics to Graphite 330 | [metrics.graphite] 331 | 332 | # Enable by setting the address setting (ex localhost:2003) 333 | ; address = 334 | ; prefix = prod.grafana.%(instance_name)s. 335 | # ################################### Distributed tracing ############ 336 | [tracing.jaeger] 337 | 338 | # Enable by setting the address sending traces to jaeger (ex localhost:6831) 339 | ; address = localhost:6831 340 | # Tag that will always be included in when creating new spans. ex (tag1:value1,tag2:value2) 341 | ; always_included_tag = tag1:value1 342 | # Type specifies the type of the sampler: const, probabilistic, rateLimiting, or remote 343 | ; sampler_type = const 344 | # jaeger samplerconfig param 345 | # for "const" sampler, 0 or 1 for always false/true respectively 346 | # for "probabilistic" sampler, a probability between 0 and 1 347 | # for "rateLimiting" sampler, the number of spans per second 348 | # for "remote" sampler, param is the same as for "probabilistic" 349 | # and indicates the initial sampling rate before the actual one 350 | # is received from the mothership 351 | ; sampler_param = 1 352 | # ################################### Grafana.com integration ########################## 353 | # Url used to to import dashboards directly from Grafana.com 354 | [grafana_com] 355 | 356 | ; url = https://grafana.com 357 | # ################################### External image storage ########################## 358 | [external_image_storage] 359 | 360 | # Used for uploading images to public servers so they can be included in slack/email messages. 361 | # you can choose between (s3, webdav, gcs, azure_blob, local) 362 | ; provider = 363 | [external_image_storage.s3] 364 | 365 | ; bucket = 366 | ; region = 367 | ; path = 368 | ; access_key = 369 | ; secret_key = 370 | [external_image_storage.webdav] 371 | 372 | ; url = 373 | ; public_url = 374 | ; username = 375 | ; password = 376 | [external_image_storage.gcs] 377 | 378 | ; key_file = 379 | ; bucket = 380 | ; path = 381 | [external_image_storage.azure_blob] 382 | 383 | ; account_name = 384 | ; account_key = 385 | ; container_name = 386 | [external_image_storage.local] 387 | 388 | -------------------------------------------------------------------------------- /data/configuration/test.toml: -------------------------------------------------------------------------------- 1 | title = "test" 2 | [constraint] 3 | name = "collectd.org" 4 | version = "0.3.0" 5 | 6 | -------------------------------------------------------------------------------- /data/cryptographic/APT.yar.aes: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazy-canux/go-devops/d37606759e16ecb763ffa6df333f1635676d2cfc/data/cryptographic/APT.yar.aes -------------------------------------------------------------------------------- /database/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | # Mysql 3 | 4 | expose 3306. 5 | 6 | launch with specify volume: 7 | 8 | $ docker run --name mymysql -v mysql-storage:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=password -d mysql:tag 9 | 10 | create database and user: 11 | 12 | $ docker run --name mymysql -v mysql-storage:/var/lib/mysql -e MYSQL_DATABASE=sandbox -e MYSQL_USER=sandbox MYSQL_PASSWORD=password -d mysql:tag 13 | 14 | files in /docker-entrypoint-initdb.d will be executed when container started(.sh,.sql,.sql.gz). 15 | 16 | $ docker run --name mymysql -v mysql-storage:/var/lib/mysql -v dbpatch:/docker-entrypoint-initdb.d -e MYSQL_DATABASE=sandbox -e MYSQL_USER=sandbox -e MYSQL_PASSWORD=password -d mysql:tag 17 | 18 | # SqlServer 19 | 20 | */ 21 | package database 22 | -------------------------------------------------------------------------------- /database/mssql.go: -------------------------------------------------------------------------------- 1 | package database 2 | 3 | import ( 4 | "database/sql" 5 | "fmt" 6 | "io/ioutil" 7 | "log" 8 | "strings" 9 | 10 | _ "github.com/denisenkom/go-mssqldb" 11 | ) 12 | 13 | func MssqlVersion(host string, port int, database, username, password string) (string, error) { 14 | connString := fmt.Sprintf("server=%s;port=%d;database=%s;user id=%s;password=%s;encrypt=disable", host, port, database, username, password) 15 | //conn, err := sql.Open("mssql", connString) 16 | conn, err := sql.Open("sqlserver", connString) 17 | if err != nil { 18 | log.Println("Parameter error.") 19 | return "", err 20 | } 21 | defer conn.Close() 22 | 23 | err = conn.Ping() 24 | if err != nil { 25 | log.Println("Connection failed.") 26 | return "", err 27 | } 28 | 29 | var version string 30 | err = conn.QueryRow(`select @@version`).Scan(&version) 31 | if err != nil { 32 | log.Println("Get version failed.") 33 | return "", err 34 | } 35 | 36 | return version, nil 37 | } 38 | 39 | func PatchMssql(host string, port int, user, pw, db string, patch string) bool { 40 | connString := fmt.Sprintf("server=%s;port=%d;database=%s;user id=%s;password=%s;encrypt=disable", host, port, db, user, pw) 41 | conn, err := sql.Open("mssql", connString) 42 | if err != nil { 43 | log.Printf("database %s parameter error: %s", host, err.Error()) 44 | return false 45 | } 46 | defer conn.Close() 47 | 48 | err = conn.Ping() 49 | if err != nil { 50 | log.Printf("Connection error: %s", err.Error()) 51 | return false 52 | } 53 | 54 | fBytes, err := ioutil.ReadFile(patch) 55 | if err != nil { 56 | log.Printf("open db script error: %s", err.Error()) 57 | return false 58 | } 59 | 60 | sqlSlice1 := strings.Split(string(fBytes), "GO") 61 | sqlSlice2 := strings.Split(strings.Join(sqlSlice1, ""), "go") 62 | query := strings.Join(sqlSlice2, "") 63 | 64 | stmt, err := conn.Prepare(query) 65 | if err != nil { 66 | log.Printf("perpare script error: %s", err.Error()) 67 | return false 68 | } 69 | defer stmt.Close() 70 | 71 | _, err = stmt.Exec() 72 | if err != nil { 73 | log.Printf("execute script error: %s", err.Error()) 74 | return false 75 | } 76 | return true 77 | } 78 | -------------------------------------------------------------------------------- /database/mssql_test.go: -------------------------------------------------------------------------------- 1 | package database 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestMssqlVersion(t *testing.T) { 8 | version, err := MssqlVersion("127.0.0.1", 1433, "db", "user", "******") 9 | if err != nil { 10 | t.Error("failed") 11 | } else { 12 | t.Log(version) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /database/mysql.go: -------------------------------------------------------------------------------- 1 | package database 2 | 3 | import ( 4 | "bytes" 5 | "database/sql" 6 | "fmt" 7 | "log" 8 | "os/exec" 9 | 10 | _ "github.com/go-sql-driver/mysql" 11 | ) 12 | 13 | func MysqlVersion(host string, port int, database, username, password string) (string, error) { 14 | connString := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", username, password, host, port, database) 15 | conn, err := sql.Open("mysql", connString) 16 | if err != nil { 17 | log.Println("Parameter error.") 18 | return "", err 19 | } 20 | defer conn.Close() 21 | 22 | err = conn.Ping() 23 | if err != nil { 24 | log.Println("Connection failed.") 25 | return "", err 26 | } 27 | 28 | var version string 29 | err = conn.QueryRow(`select version()`).Scan(&version) 30 | if err == nil { 31 | log.Println("Get version failed.") 32 | return "", err 33 | } 34 | return version, nil 35 | } 36 | 37 | func PatchMysql(host string, port int, user, pw, db string, patch string) bool { 38 | var stdout, stderr bytes.Buffer 39 | h := fmt.Sprintf("-h%s", host) 40 | P := fmt.Sprintf("-P%d", port) 41 | u := fmt.Sprintf("-u%s", user) 42 | p := fmt.Sprintf("-p%s", pw) 43 | d := fmt.Sprintf("-D%s", db) 44 | query := fmt.Sprintf("source %s", patch) 45 | cmd := exec.Command("mysql", h, P, u, p, d, "-e", query) 46 | cmd.Stdout = &stdout 47 | cmd.Stderr = &stderr 48 | err := cmd.Run() 49 | log.Printf("stdout: %s", stdout.String()) 50 | log.Printf("stderr: %s", stderr.String()) 51 | if err != nil { 52 | log.Printf("execute script error: %s", err.Error()) 53 | return false 54 | } 55 | return true 56 | } 57 | -------------------------------------------------------------------------------- /database/mysql_test.go: -------------------------------------------------------------------------------- 1 | package database 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestMysqlVersion(t *testing.T) { 8 | version, err := MysqlVersion("127.0.0.1", 3306, "sandbox", "sandbox", "password") 9 | if err != nil { 10 | t.Errorf("failed: %s", err) 11 | } else { 12 | t.Log(version) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | go-devops 3 | 1.0.0 4 | */ 5 | package go_devops 6 | -------------------------------------------------------------------------------- /docker/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | docker 3 | 4 | 5 | default client: 6 | 7 | github.com/docker/docker v1.13.1 8 | 9 | 10 | avaliable client: 11 | 12 | go get -v github.com/docker/engine@v18.09.9 13 | github.com/docker/docker v1.13.1 => github.com/docker/engine v1.4.2-0.20190822180741-9552f2b2fdde 14 | 15 | */ 16 | package docker 17 | -------------------------------------------------------------------------------- /docker/docker.go: -------------------------------------------------------------------------------- 1 | package docker 2 | 3 | import ( 4 | "errors" 5 | "log" 6 | 7 | "github.com/docker/docker/api/types" 8 | "github.com/docker/docker/api/types/network" 9 | "github.com/docker/docker/client" 10 | "golang.org/x/net/context" 11 | ) 12 | 13 | var cli *client.Client 14 | 15 | func init() { 16 | var err error 17 | cli, err = client.NewClientWithOpts(client.WithVersion("1.39")) 18 | if err != nil { 19 | log.Fatal("New Client failed.") 20 | } 21 | } 22 | 23 | func ServiceCheck(name string) bool { 24 | containers, err := cli.ContainerList( 25 | context.Background(), 26 | types.ContainerListOptions{ 27 | All: true, 28 | }) 29 | if err != nil { 30 | log.Fatalf("List containers failed: %s", err.Error()) 31 | } 32 | for _, container := range containers { 33 | if container.Names[0] == ("/" + name) { 34 | log.Printf("Container %s, status: %s, state: %s.", container.Names[0], container.Status, container.State) 35 | if container.State == "running" { 36 | return true 37 | } else { 38 | return false 39 | } 40 | } 41 | } 42 | log.Printf("Container %s not exist.", name) 43 | return false 44 | } 45 | 46 | func CreateNetwork(name, driver, subnet, gateway string) (string, error) { 47 | options := types.NetworkCreate{ 48 | CheckDuplicate: true, 49 | Driver: driver, 50 | IPAM: &network.IPAM{ 51 | Driver: "default", 52 | Config: []network.IPAMConfig{ 53 | { 54 | Subnet: subnet, 55 | Gateway: gateway, 56 | }, 57 | }, 58 | }, 59 | Options: map[string]string{ 60 | "com.docker.network.bridge.name": name, 61 | }, 62 | } 63 | resp, err := cli.NetworkCreate(context.Background(), name, options) 64 | if err != nil { 65 | log.Fatalf("Create Docker Network %s failed: %s", name, err.Error()) 66 | return "", errors.New("create docker network failed") 67 | } 68 | return resp.ID, nil 69 | } 70 | 71 | func RemoveNetwork(name string) bool { 72 | id, err := NetworkId(name) 73 | if err != nil { 74 | log.Fatalf("Docker Network %s not exist.", name) 75 | } else { 76 | err := cli.NetworkRemove(context.Background(), id) 77 | if err != nil { 78 | log.Fatalf("Remove Docker Network %s failed: %s", name, err.Error()) 79 | return false 80 | } 81 | } 82 | log.Fatalf("Remove Docker Network %s succeed.", name) 83 | return true 84 | } 85 | 86 | func NetworkId(name string) (string, error) { 87 | networks, err := cli.NetworkList(context.Background(), types.NetworkListOptions{}) 88 | if err != nil { 89 | log.Fatalf("List docker network failed: %s", err.Error()) 90 | } 91 | for _, network := range networks { 92 | if name == network.Name { 93 | log.Printf("Docker network %s exist.", name) 94 | return network.ID, nil 95 | } 96 | } 97 | return "", errors.New("docker network not exist") 98 | } 99 | -------------------------------------------------------------------------------- /docker/docker_test.go: -------------------------------------------------------------------------------- 1 | package docker 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestNetwork(t *testing.T) { 8 | id, err := CreateNetwork("lan0", "bridge", "92.168.1.0/24", "192.168.1.1") 9 | if err != nil { 10 | t.Errorf("create network error: %v", err) 11 | } else { 12 | t.Log(id) 13 | } 14 | result := RemoveNetwork("lan0") 15 | if result { 16 | t.Log("remove network pass") 17 | } else { 18 | t.Error("remove network failed.") 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /email/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | gomail 3 | */ 4 | package email 5 | -------------------------------------------------------------------------------- /email/gomail.go: -------------------------------------------------------------------------------- 1 | package email 2 | 3 | import ( 4 | "crypto/tls" 5 | "gopkg.in/gomail.v2" 6 | "log" 7 | ) 8 | 9 | // Send PlainText. 10 | func SendText(host string, port int, username, password string, to []string, from, cc, subject, body string) error { 11 | addresses := make([]string, len(to)) 12 | 13 | m := gomail.NewMessage() 14 | m.SetHeader("From", from) 15 | for i := range addresses { 16 | addresses[i] = m.FormatAddress(to[i], "") 17 | } 18 | m.SetHeader("To", addresses...) 19 | m.SetAddressHeader("Cc", cc, "") 20 | m.SetHeader("Subject", subject) 21 | m.SetBody("text/plain", body) 22 | //m.Attach() 23 | 24 | d := gomail.Dialer{ 25 | Host: host, 26 | Port: port, 27 | Username: username, 28 | Password: password, 29 | } 30 | d.TLSConfig = &tls.Config{InsecureSkipVerify: true} 31 | if err := d.DialAndSend(m); err != nil { 32 | log.Println("Send email failed.") 33 | return err 34 | } 35 | return nil 36 | } 37 | -------------------------------------------------------------------------------- /email/gomail_test.go: -------------------------------------------------------------------------------- 1 | package email 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestSendText(t *testing.T) { 8 | err := SendText("mail.domain.com", 25, "", "", []string{"canuxcheng@gmail.com"}, "go-devops@domain.com", "", "subject", "body") 9 | if err != nil { 10 | t.Error("failed") 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /firewall/iptables.go: -------------------------------------------------------------------------------- 1 | package firewall 2 | 3 | import ( 4 | "fmt" 5 | "github.com/coreos/go-iptables/iptables" 6 | "github.com/crazy-canux/go-devops/utils" 7 | "log" 8 | "strconv" 9 | ) 10 | 11 | var ipts = map[string][]string{ 12 | "filter": { 13 | "INPUT", 14 | "OUTPUT", 15 | "FORWARD", 16 | }, 17 | "nat": { 18 | "INPUT", 19 | "OUTPUT", 20 | "PREROUTING", 21 | "POSTROUTING", 22 | }, 23 | "mangle": { 24 | "INPUT", 25 | "OUTPUT", 26 | "FORWARD", 27 | "PREROUTING", 28 | "POSTROUTING", 29 | }, 30 | } 31 | 32 | var ipt *iptables.IPTables 33 | 34 | func init() { 35 | var err error 36 | ipt, err = iptables.New() 37 | if err != nil { 38 | log.Fatalf("get iptables failed: %s", err.Error()) 39 | } 40 | } 41 | 42 | func CleanUDC() { 43 | for table := range ipts { 44 | chains := ListChain(table) 45 | for _, chain := range chains { 46 | if !utils.In(chain, ipts[table]) { 47 | ClearChain(table, chain) 48 | DeleteChain(table, chain) 49 | } 50 | } 51 | } 52 | } 53 | 54 | func CleanRules(table, chain string) { 55 | if table != "" { 56 | if chain != "" { 57 | ClearChain(table, chain) 58 | } else { 59 | for _, chain := range ipts[table] { 60 | ClearChain(table, chain) 61 | } 62 | } 63 | } else { 64 | for table := range ipts { 65 | for _, chain := range ipts[table] { 66 | ClearChain(table, chain) 67 | } 68 | } 69 | } 70 | } 71 | 72 | func AppendRules(table, chain string, rule []string) { 73 | err := ipt.AppendUnique(table, chain, rule...) 74 | if err != nil { 75 | log.Fatalf("Appendunique failed: %s", err.Error()) 76 | } 77 | } 78 | 79 | func InsertRules(table, chain string, position int, rule []string) { 80 | err := ipt.Insert(table, chain, position, rule...) 81 | if err != nil { 82 | log.Fatalf("Insert failed: %s", err.Error()) 83 | } 84 | } 85 | 86 | func DeleteRules(table, chain string, rule []string) { 87 | // delete rules in table-chain, iptables -t table -D chain rulenum 88 | err := ipt.Delete(table, chain, rule...) 89 | if err != nil { 90 | log.Fatalf("Delete failed: %s", err.Error()) 91 | } 92 | } 93 | 94 | func Version() string { 95 | // get version 96 | major, minor, patch := ipt.GetIptablesVersion() 97 | return strconv.Itoa(major) + "." + strconv.Itoa(minor) + "." + strconv.Itoa(patch) 98 | } 99 | 100 | func List(table, chain string) []string { 101 | // iptables -t -S 102 | rules, err := ipt.List(table, chain) 103 | if err != nil { 104 | log.Fatalf("list failed: %s", err.Error()) 105 | } 106 | for _, rule := range rules { 107 | fmt.Println(rule) 108 | } 109 | return rules 110 | } 111 | 112 | func ListWithCounters(table, chain string) []string { 113 | // iptables -t
-L --line-number 114 | rules, err := ipt.ListWithCounters(table, chain) 115 | if err != nil { 116 | log.Fatalf("listwithcounters failed: %s", err.Error()) 117 | } 118 | for _, rule := range rules { 119 | fmt.Println(rule) 120 | } 121 | return rules 122 | } 123 | 124 | func ListChain(table string) []string { 125 | chains, err := ipt.ListChains(table) 126 | if err != nil { 127 | log.Fatalf("listchains in %s failed: %s", table, err.Error()) 128 | } 129 | for _, chain := range chains { 130 | fmt.Println(chain) 131 | } 132 | return chains 133 | } 134 | 135 | func ClearChain(table, chain string) { 136 | // clear rules in table-chain, iptables -t table -F chain 137 | err := ipt.ClearChain(table, chain) 138 | if err != nil { 139 | log.Fatalf("Clear rules in %s-%s failed: %s", table, chain, err.Error()) 140 | } 141 | } 142 | 143 | func DeleteChain(table, chain string) { 144 | // delete chain in table, iptables -t table -X [chain] 145 | err := ipt.DeleteChain(table, chain) 146 | if err != nil { 147 | log.Fatalf("deletechain %s-%s failed: %s", table, chain, err.Error()) 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /firewall/iptables_test.go: -------------------------------------------------------------------------------- 1 | package firewall 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestVersion(t *testing.T) { 8 | t.Log(Version()) 9 | } 10 | -------------------------------------------------------------------------------- /flag/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | cobra 4 | 5 | https://github.com/spf13/cobra 6 | 7 | run order: 8 | 9 | 1. PersistentPreRun 10 | 2. PreRun 11 | 3. Run 12 | 4. PostRun 13 | 5. PersistentPostRun 14 | 15 | subCmd's Persistent*Run will cover rootCmd's. 16 | 17 | kinpin 18 | 19 | https://github.com/alecthomas/kingpin 20 | 21 | */ 22 | package flag 23 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/crazy-canux/go-devops 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect 7 | github.com/Microsoft/go-winio v0.4.14 // indirect 8 | github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect 9 | github.com/coreos/go-iptables v0.4.3 10 | github.com/denisenkom/go-mssqldb v0.0.0-20191001013358-cfbb681360f0 11 | github.com/docker/distribution v2.7.1+incompatible // indirect 12 | github.com/docker/docker v1.13.1 13 | github.com/docker/go-connections v0.4.0 // indirect 14 | github.com/docker/go-units v0.4.0 // indirect 15 | github.com/go-ini/ini v1.51.0 16 | github.com/go-redis/redis v6.15.6+incompatible 17 | github.com/go-sql-driver/mysql v1.6.0 18 | github.com/gogo/protobuf v1.3.1 // indirect 19 | github.com/google/go-cmp v0.3.1 // indirect 20 | github.com/gorilla/mux v1.7.3 // indirect 21 | github.com/influxdata/influxdb v1.7.9 22 | github.com/kr/pretty v0.1.0 // indirect 23 | github.com/onsi/ginkgo v1.10.3 // indirect 24 | github.com/onsi/gomega v1.7.1 // indirect 25 | github.com/opencontainers/go-digest v1.0.0-rc1 // indirect 26 | github.com/opencontainers/image-spec v1.0.1 // indirect 27 | github.com/smartystreets/goconvey v1.6.4 // indirect 28 | github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271 29 | github.com/stretchr/testify v1.4.0 // indirect 30 | golang.org/x/crypto v0.0.0-20191111213947-16651526fdb4 31 | golang.org/x/net v0.0.0-20191109021931-daa7c04131f5 32 | golang.org/x/sys v0.0.0-20191110163157-d32e6e3b99c4 // indirect 33 | golang.org/x/text v0.3.2 // indirect 34 | golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect 35 | google.golang.org/grpc v1.25.1 // indirect 36 | gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect 37 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect 38 | gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df 39 | gopkg.in/ini.v1 v1.50.0 // indirect 40 | gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 41 | gopkg.in/yaml.v2 v2.2.5 // indirect 42 | gotest.tools v2.2.0+incompatible // indirect 43 | ) 44 | 45 | replace ( 46 | github.com/docker/docker v1.13.1 => github.com/docker/engine v1.4.2-0.20190822180741-9552f2b2fdde 47 | golang.org/x/crypto v0.0.0-20191106202628-ed6320f186d4 => github.com/golang/crypto v0.0.0-20191106202628-ed6320f186d4 48 | golang.org/x/net v0.0.0-20191105084925-a882066a44e0 => github.com/golang/net v0.0.0-20191105084925-a882066a44e0 49 | ) 50 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= 3 | github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= 4 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 5 | github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU= 6 | github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= 7 | github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= 8 | github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= 9 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 10 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 11 | github.com/coreos/go-iptables v0.4.3 h1:jJg1aFuhCqWbgBl1VTqgTHG5faPM60A5JDMjQ2HYv+A= 12 | github.com/coreos/go-iptables v0.4.3/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= 13 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 14 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 15 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 16 | github.com/denisenkom/go-mssqldb v0.0.0-20191001013358-cfbb681360f0 h1:epsH3lb7KVbXHYk7LYGN5EiE0MxcevHU85CKITJ0wUY= 17 | github.com/denisenkom/go-mssqldb v0.0.0-20191001013358-cfbb681360f0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= 18 | github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= 19 | github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= 20 | github.com/docker/engine v1.4.2-0.20190822180741-9552f2b2fdde h1:aq0cubQTR2dVP78fiRSh2GfLAuadJ2DdGHKR66Jdmls= 21 | github.com/docker/engine v1.4.2-0.20190822180741-9552f2b2fdde/go.mod h1:3CPr2caMgTHxxIAZgEMd3uLYPDlRvPqCpyeRf6ncPcY= 22 | github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= 23 | github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= 24 | github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= 25 | github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= 26 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 27 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 28 | github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= 29 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 30 | github.com/go-ini/ini v1.51.0 h1:VPJKXGzbKlyExUE8f41aV57yxkYx5R49yR6n7flp0M0= 31 | github.com/go-ini/ini v1.51.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= 32 | github.com/go-redis/redis v6.15.6+incompatible h1:H9evprGPLI8+ci7fxQx6WNZHJSb7be8FqJQRhdQZ5Sg= 33 | github.com/go-redis/redis v6.15.6+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= 34 | github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= 35 | github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= 36 | github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= 37 | github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= 38 | github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= 39 | github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= 40 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= 41 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 42 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 43 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 44 | github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= 45 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 46 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 47 | github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= 48 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 49 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= 50 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 51 | github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= 52 | github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= 53 | github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= 54 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 55 | github.com/influxdata/influxdb v1.7.9 h1:uSeBTNO4rBkbp1Be5FKRsAmglM9nlx25TzVQRQt1An4= 56 | github.com/influxdata/influxdb v1.7.9/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= 57 | github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= 58 | github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= 59 | github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= 60 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 61 | github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= 62 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 63 | github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 64 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 65 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 66 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 67 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 68 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 69 | github.com/onsi/ginkgo v1.10.3 h1:OoxbjfXVZyod1fmWYhI7SEyaD8B00ynP3T+D5GiyHOY= 70 | github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 71 | github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ= 72 | github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= 73 | github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ= 74 | github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= 75 | github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= 76 | github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= 77 | github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= 78 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 79 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 80 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 81 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 82 | github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= 83 | github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= 84 | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= 85 | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= 86 | github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= 87 | github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= 88 | github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271 h1:WhxRHzgeVGETMlmVfqhRn8RIeeNoPr2Czh33I4Zdccw= 89 | github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= 90 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 91 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 92 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 93 | github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= 94 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 95 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 96 | golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 97 | golang.org/x/crypto v0.0.0-20191111213947-16651526fdb4 h1:AGVXd+IAyeAb3FuQvYDYQ9+WR2JHm0+C0oYJaU1C4rs= 98 | golang.org/x/crypto v0.0.0-20191111213947-16651526fdb4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 99 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 100 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 101 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 102 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 103 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 104 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 105 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 106 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 107 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 108 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 109 | golang.org/x/net v0.0.0-20191109021931-daa7c04131f5 h1:bHNaocaoJxYBo5cw41UyTMLjYlb8wPY7+WFrnklbHOM= 110 | golang.org/x/net v0.0.0-20191109021931-daa7c04131f5/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 111 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 112 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 113 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 114 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 115 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 116 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 117 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 118 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 119 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 120 | golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 121 | golang.org/x/sys v0.0.0-20191110163157-d32e6e3b99c4 h1:Hynbrlo6LbYI3H1IqXpkVDOcX/3HiPdhVEuyj5a59RM= 122 | golang.org/x/sys v0.0.0-20191110163157-d32e6e3b99c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 123 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 124 | golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= 125 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 126 | golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= 127 | golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 128 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 129 | golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 130 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 131 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 132 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 133 | golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 134 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 135 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 136 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 137 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 138 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= 139 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 140 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 141 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 142 | google.golang.org/grpc v1.25.1 h1:wdKvqQk7IttEw92GoRyKG2IDrUIpgpj6H6m81yfeMW0= 143 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 144 | gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= 145 | gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= 146 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 147 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= 148 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 149 | gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= 150 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 151 | gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE= 152 | gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw= 153 | gopkg.in/ini.v1 v1.50.0 h1:c/4YI/GUgB7d2yOkxdsQyYDhW67nWrTl6Zyd9vagYmg= 154 | gopkg.in/ini.v1 v1.50.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= 155 | gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3vEUnzSCL1nVjPhqrw= 156 | gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= 157 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= 158 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 159 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 160 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 161 | gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c= 162 | gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 163 | gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= 164 | gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= 165 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 166 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 167 | -------------------------------------------------------------------------------- /grafana/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | # Grafana 3 | 4 | launch: 5 | 6 | docker run -d --name=grafana -p 3000:3000 grafana/grafana:tag 7 | 8 | launch with volume: 9 | 10 | $ docker volume create grafana-storage 11 | 12 | $ docker run -d --name=grafana -p 3000:3000 \ 13 | -v grafana-storage:/var/lib/grafana \ 14 | grafana/grafana:tag 15 | */ 16 | package grafana 17 | -------------------------------------------------------------------------------- /http/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | # httpd/apach2 3 | 4 | copy html in Dockerfile: 5 | 6 | FROM httpd:tag 7 | COPY ./web/ /usr/local/apache2/htdocs/ 8 | 9 | launch your apache with specify port: 10 | 11 | $ docker run -dit --name admin-gui -p 80:80 -p 443:443 myweb:tag 12 | 13 | # haproxy 14 | 15 | */ 16 | package http 17 | -------------------------------------------------------------------------------- /http/http.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "bytes" 5 | "crypto/tls" 6 | "errors" 7 | "io" 8 | "io/ioutil" 9 | "log" 10 | "net/http" 11 | ) 12 | 13 | func Get(uri string, username, password interface{}) (io.ReadCloser, error) { 14 | var nop []byte 15 | body := ioutil.NopCloser(bytes.NewBuffer(nop)) 16 | 17 | req, err := http.NewRequest("GET", uri, nil) 18 | if err != nil { 19 | log.Printf("Create NewRequest error: %s", err.Error()) 20 | return body, err 21 | } 22 | uname, ok1 := username.(string) 23 | pw, ok2 := password.(string) 24 | if ok1 && ok2 { 25 | req.SetBasicAuth(uname, pw) 26 | } 27 | req.Header.Set("Content-Type", "application/json") 28 | 29 | tc := &tls.Config{InsecureSkipVerify: true} 30 | tp := &http.Transport{TLSClientConfig: tc} 31 | client := &http.Client{Transport: tp} 32 | 33 | resp, err := client.Do(req) 34 | if err != nil { 35 | log.Printf("Do Get error: %s", err.Error()) 36 | return resp.Body, err 37 | } 38 | 39 | // TODO: 200, 201,... 40 | if resp.StatusCode != 200 { 41 | log.Printf("Get failed: %s", resp.Status) 42 | return resp.Body, errors.New(resp.Status) 43 | } 44 | return resp.Body, nil 45 | } 46 | 47 | func Post(url string, payload []byte, username, password interface{}) (io.ReadCloser, error) { 48 | var nop []byte 49 | body := ioutil.NopCloser(bytes.NewBuffer(nop)) 50 | 51 | req, err := http.NewRequest("POST", url, bytes.NewBuffer(payload)) 52 | if err != nil { 53 | log.Printf("Create NewRequest error: %s", err.Error()) 54 | return body, err 55 | } 56 | uname, ok1 := username.(string) 57 | pw, ok2 := password.(string) 58 | if ok1 && ok2 { 59 | req.SetBasicAuth(uname, pw) 60 | } 61 | req.Header.Set("Content-Type", "application/json") 62 | 63 | tc := &tls.Config{InsecureSkipVerify: true} 64 | tp := &http.Transport{TLSClientConfig: tc} 65 | client := &http.Client{Transport: tp} 66 | 67 | resp, err := client.Do(req) 68 | if err != nil { 69 | log.Printf("Do Post error: %s", err.Error()) 70 | return resp.Body, err 71 | } 72 | 73 | if resp.StatusCode != 200 { 74 | log.Printf("Post failed: %s", resp.Status) 75 | return resp.Body, errors.New(resp.Status) 76 | } 77 | return resp.Body, nil 78 | } 79 | -------------------------------------------------------------------------------- /http/http_test.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io/ioutil" 7 | "log" 8 | "testing" 9 | ) 10 | 11 | type ScenarioCost struct { 12 | ScenarioLine int `json:"scenario_line"` 13 | TaskGroupName string `json:"task_group_name"` 14 | MaxRuntimeSecs float64 `json:"max_runtime_secs"` 15 | } 16 | 17 | func TestGet(t *testing.T) { 18 | body, err := Get("https://localhost/", "user", "pw") 19 | if err != nil { 20 | t.Error("get failed.") 21 | } 22 | defer body.Close() 23 | content, _ := ioutil.ReadAll(body) 24 | log.Println(string(content)) 25 | } 26 | 27 | func TestPost(t *testing.T) { 28 | s1 := ScenarioCost{ 29 | ScenarioLine: 1, 30 | TaskGroupName: "task1", 31 | MaxRuntimeSecs: 1, 32 | } 33 | s2 := ScenarioCost{ 34 | ScenarioLine: 2, 35 | TaskGroupName: "task2", 36 | MaxRuntimeSecs: 2, 37 | } 38 | scenarioCosts := []ScenarioCost{s1, s2} 39 | fmt.Println(scenarioCosts) 40 | payload, err := json.Marshal(scenarioCosts) 41 | if err != nil { 42 | t.Error("obj to json failed.") 43 | fmt.Println(err.Error()) 44 | } 45 | fmt.Println(string(payload)) 46 | 47 | body, _ := Post( 48 | "https://localhost/", payload, "user", "pw") 49 | defer body.Close() 50 | content, _ := ioutil.ReadAll(body) 51 | fmt.Println(string(content)) 52 | } 53 | -------------------------------------------------------------------------------- /http/wget.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "io" 5 | "log" 6 | "os" 7 | ) 8 | 9 | func Download(uri string, file string, username, password interface{}) bool { 10 | out, err := os.Create(file) 11 | if err != nil { 12 | log.Printf("Create destination file error: %s", err.Error()) 13 | return false 14 | } 15 | defer out.Close() 16 | 17 | body, err := Get(uri, username, password) 18 | if err != nil { 19 | log.Printf("Get source file error: %s", err.Error()) 20 | return false 21 | } 22 | _, err = io.Copy(out, body) 23 | if err != nil { 24 | log.Printf("Copy file error: %s", err.Error()) 25 | return false 26 | } 27 | return true 28 | } 29 | -------------------------------------------------------------------------------- /http/wget_test.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestDownload(t *testing.T) { 8 | result := Download("https://127.0.0.1/path/to/file", 9 | "/path/to/file", 10 | "sandbox", "******") 11 | if result { 12 | t.Log("yes") 13 | } else { 14 | t.Error("no") 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /log/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | zap 4 | 5 | https://github.com/uber-go/zap 6 | 7 | logrus 8 | 9 | https://github.com/sirupsen/logrus 10 | 11 | */ 12 | package log 13 | -------------------------------------------------------------------------------- /nosql/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | # Redis 3 | 4 | expose 6379 and storage in /data. 5 | 6 | launch with specify volume: 7 | 8 | $ docker run --name myredis -v redis-storage:/data -d redis redis-server --appendonly yes 9 | 10 | # Mongo 11 | 12 | */ 13 | 14 | package nosql 15 | -------------------------------------------------------------------------------- /nosql/mongo.go: -------------------------------------------------------------------------------- 1 | package nosql 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | 7 | "gopkg.in/mgo.v2" 8 | "gopkg.in/mgo.v2/bson" 9 | ) 10 | 11 | type Status struct { 12 | Host string `bson:"host"` 13 | Version string `bson:"version"` 14 | Process string `bson:"process"` 15 | Pid int64 `bson:"pid"` 16 | Uptime int64 `bson:"uptime"` 17 | UptimeMillis int64 `bson:"uptimeMillis"` 18 | UptimeEstimate int64 `bson:"uptimeEstimate"` 19 | Asserts map[string]int64 `bson:"asserts"` 20 | ShardCursorType map[string]interface{} `bson:"shardCursorType"` 21 | StorageEngine map[string]string `bson:"storageEngine"` 22 | } 23 | 24 | func ServerStatus(ip string) (*Status, error) { 25 | var status = &Status{} 26 | uri := fmt.Sprintf("mongodb://%s", ip) 27 | session, err := mgo.Dial(uri) 28 | if err != nil { 29 | log.Println("Dial failed.") 30 | return status, err 31 | } 32 | defer session.Close() 33 | 34 | err = session.Ping() 35 | if err != nil { 36 | log.Println("ping failed.") 37 | return status, err 38 | } 39 | 40 | err = session.Run( 41 | bson.D{ 42 | {Name: "serverStatus"}, 43 | {Value: 1}, 44 | }, 45 | status, 46 | ) 47 | if err != nil { 48 | log.Println("Get serverStatus failed.") 49 | return status, err 50 | } 51 | return status, err 52 | } 53 | -------------------------------------------------------------------------------- /nosql/mongo_test.go: -------------------------------------------------------------------------------- 1 | package nosql 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestServerStatus(t *testing.T) { 8 | status, err := ServerStatus("127.0.0.1:27017") 9 | if err != nil { 10 | t.Errorf("failed: %s", err) 11 | } else { 12 | t.Logf("%v", status.Host) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /nosql/redis.go: -------------------------------------------------------------------------------- 1 | package nosql 2 | 3 | import ( 4 | "github.com/go-redis/redis" 5 | "log" 6 | ) 7 | 8 | func Info(ip, pw string, db int) (string, error) { 9 | client := redis.NewClient( 10 | &redis.Options{ 11 | Addr: ip, 12 | Password: pw, 13 | DB: db, 14 | }, 15 | ) 16 | defer client.Close() 17 | 18 | ping, err := client.Ping().Result() 19 | if err != nil { 20 | log.Printf("Connection failed: %s", ping) 21 | return "", err 22 | } 23 | info, err := client.Info().Result() 24 | if err != nil { 25 | log.Printf("Get info failed: %s", info) 26 | return "", err 27 | } 28 | return info, nil 29 | } 30 | -------------------------------------------------------------------------------- /nosql/redis_test.go: -------------------------------------------------------------------------------- 1 | package nosql 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestInfo(t *testing.T) { 8 | info, err := Info("127.0.0.1:6379", "", 0) 9 | if err != nil { 10 | t.Error("failed") 11 | } else { 12 | t.Log(info) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /rabbitmq/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | # Rabbitmq 4 | 5 | rabbitmq:tag default expose 5672. 6 | 7 | rabbitmq:tag-management default expost 5672 and 15672. 8 | 9 | storage: /var/lib/rabbitmq 10 | 11 | launch with management: 12 | 13 | # http://ip:15672 guest/guest 14 | $ docker run --hostname mq-node1 --name rabbitmq-node1 -d rabbitmq:tag-management 15 | 16 | launch with specify auth for management: 17 | 18 | # http://ip:15672 sandbox/password 19 | $ docker run -v rabbitmq-storage:/var/lib/rabbitmq --hostname mq-node1 --name rabbitmq-node1 -e RABBITMQ_DEFAULT_USER=sandbox -e RABBITMQ_DEFAULT_PASS=password -d rabbitmq:tag-management 20 | 21 | # Rabbitmq-HAProxy 22 | 23 | specify erlang cookie: 24 | 25 | $ docker run --hostname mq-master -e RABBITMQ_ERLANG_COOKIE='secret cookie here' -d rabbitmq:tag-management 26 | 27 | */ 28 | package rabbitmq 29 | -------------------------------------------------------------------------------- /rabbitmq/rabbitmq.go: -------------------------------------------------------------------------------- 1 | package rabbitmq 2 | 3 | import ( 4 | "github.com/streadway/amqp" 5 | "log" 6 | "time" 7 | ) 8 | 9 | func Ping(url string, timeout string) bool { 10 | to, _ := time.ParseDuration(timeout) 11 | after := time.Now().Add(to) 12 | for { 13 | conn, err := amqp.Dial(url) 14 | if err == nil { 15 | defer conn.Close() 16 | log.Println("Rabbitmq is available.") 17 | return true 18 | } 19 | time.Sleep(1 * time.Second) 20 | if time.Now().After(after) { 21 | log.Println("Connection Timeout.") 22 | break 23 | } 24 | } 25 | return false 26 | } 27 | -------------------------------------------------------------------------------- /rabbitmq/rabbitmq_test.go: -------------------------------------------------------------------------------- 1 | package rabbitmq 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestPing(t *testing.T) { 8 | result := Ping("amqp://user:******@127.0.0.1:5672/", "10s") 9 | if result { 10 | t.Log("pass.") 11 | } else { 12 | t.Error("failed.") 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ssh/auth.go: -------------------------------------------------------------------------------- 1 | package ssh 2 | 3 | import ( 4 | "io/ioutil" 5 | "net" 6 | "time" 7 | 8 | "golang.org/x/crypto/ssh" 9 | ) 10 | 11 | //PrivateKey Loads a private and public key from "path" and returns a SSH ClientConfig to authenticate with the server 12 | func PrivateKey(username string, path string) (ssh.ClientConfig, error) { 13 | privateKey, err := ioutil.ReadFile(path) 14 | 15 | if err != nil { 16 | return ssh.ClientConfig{}, err 17 | } 18 | 19 | signer, err := ssh.ParsePrivateKey(privateKey) 20 | 21 | if err != nil { 22 | return ssh.ClientConfig{}, err 23 | } 24 | 25 | return ssh.ClientConfig{ 26 | User: username, 27 | Auth: []ssh.AuthMethod{ 28 | ssh.PublicKeys(signer), 29 | }, 30 | HostKeyCallback: ssh.InsecureIgnoreHostKey(), 31 | Timeout: time.Minute, 32 | }, nil 33 | } 34 | 35 | func PrivateKeyWithPassphrase(username string, passpharase []byte, path string) (ssh.ClientConfig, error) { 36 | privateKey, err := ioutil.ReadFile(path) 37 | 38 | if err != nil { 39 | return ssh.ClientConfig{}, err 40 | } 41 | signer, err := ssh.ParsePrivateKeyWithPassphrase(privateKey, passpharase) 42 | 43 | if err != nil { 44 | return ssh.ClientConfig{}, err 45 | } 46 | 47 | return ssh.ClientConfig{ 48 | User: username, 49 | Auth: []ssh.AuthMethod{ 50 | ssh.PublicKeys(signer), 51 | }, 52 | HostKeyCallback: ssh.InsecureIgnoreHostKey(), 53 | Timeout: time.Minute, 54 | }, nil 55 | } 56 | 57 | func PasswordKey(username string, password string) (ssh.ClientConfig, error) { 58 | //var hostKey ssh.PublicKey 59 | return ssh.ClientConfig{ 60 | User: username, 61 | Auth: []ssh.AuthMethod{ 62 | ssh.Password(password), 63 | }, 64 | //HostKeyCallback: ssh.InsecureIgnoreHostKey(), 65 | HostKeyCallback: ssh.HostKeyCallback(func(hostname string, remote net.Addr, key ssh.PublicKey) error { return nil }), 66 | //HostKeyCallback: ssh.FixedHostKey(hostKey), 67 | Timeout: time.Minute, 68 | }, nil 69 | } -------------------------------------------------------------------------------- /ssh/client.go: -------------------------------------------------------------------------------- 1 | package ssh 2 | 3 | import ( 4 | "bytes" 5 | "errors" 6 | "fmt" 7 | "io" 8 | "io/ioutil" 9 | "log" 10 | "os" 11 | "path" 12 | "strings" 13 | "sync" 14 | "time" 15 | 16 | "golang.org/x/crypto/ssh" 17 | ) 18 | 19 | type Client struct { 20 | // the host to connect to 21 | Host string 22 | 23 | // the client config to use 24 | ClientConfig *ssh.ClientConfig 25 | 26 | // stores the SSH session while the connection is running 27 | Session *ssh.Session 28 | 29 | // stores the SSH connection itself in order to close it after transfer 30 | Conn ssh.Conn 31 | 32 | // the clients waits for the given timeout until given up the connection 33 | Timeout time.Duration 34 | 35 | // the absolute path to the remote SCP binary 36 | RemoteBinary string 37 | 38 | // password for sudo command 39 | Password string 40 | } 41 | 42 | // Connects to the remote SSH server, returns error if it couldn't establish a session to the SSH server 43 | func (a *Client) Connect() error { 44 | client, err := ssh.Dial("tcp", a.Host, a.ClientConfig) 45 | if err != nil { 46 | return err 47 | } 48 | 49 | a.Conn = client.Conn 50 | a.Session, err = client.NewSession() 51 | if err != nil { 52 | return err 53 | } 54 | return nil 55 | } 56 | 57 | //Copies the contents of an os.File to a remote location, it will get the length of the file by looking it up from the filesystem 58 | func (a *Client) CopyFromFile(file os.File, remotePath string, permissions string) error { 59 | stat, _ := file.Stat() 60 | return a.Copy(&file, remotePath, permissions, stat.Size()) 61 | } 62 | 63 | // Copies the contents of an io.Reader to a remote location, the length is determined by reading the io.Reader until EOF 64 | // if the file length in know in advance please use "Copy" instead 65 | func (a *Client) CopyFile(fileReader io.Reader, remotePath string, permissions string) error { 66 | contents_bytes, _ := ioutil.ReadAll(fileReader) 67 | bytes_reader := bytes.NewReader(contents_bytes) 68 | 69 | return a.Copy(bytes_reader, remotePath, permissions, int64(len(contents_bytes))) 70 | } 71 | 72 | // Run run a shell command on remote server. 73 | func (a *Client) Run(cmd string) (string, string, error) { 74 | var stdOut, stdErr bytes.Buffer 75 | a.Session.Stdout = &stdOut 76 | a.Session.Stderr = &stdErr 77 | 78 | var wg sync.WaitGroup 79 | wg.Add(1) 80 | errCh := make(chan error, 1) 81 | 82 | go func() { 83 | defer wg.Done() 84 | err := a.Session.Run(cmd) 85 | if err != nil { 86 | errCh <- err 87 | return 88 | } 89 | }() 90 | 91 | if waitTimeout(&wg, a.Timeout) { 92 | return "", "", errors.New("command timeout") 93 | } 94 | 95 | close(errCh) 96 | for err := range errCh { 97 | if err != nil { 98 | return "", "", err 99 | } 100 | } 101 | 102 | return stdOut.String(), stdErr.String(), nil 103 | } 104 | 105 | // Run run a shell command on remote server with sudo. 106 | func (a *Client) RunWithSudo(cmd string ) (string, string, error) { 107 | var stdOut, stdErr bytes.Buffer 108 | a.Session.Stdout = &stdOut 109 | a.Session.Stderr = &stdErr 110 | 111 | // set up terminal modes 112 | modes := ssh.TerminalModes{ 113 | ssh.ECHO: 0, // disable echoing 114 | ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud 115 | ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud 116 | } 117 | // request pseudo terminal 118 | err := a.Session.RequestPty("xterm", 80, 40, modes) 119 | if err != nil { 120 | log.Printf("set pty error: %s", err.Error()) 121 | return "", "", err 122 | } 123 | // get input 124 | in, err := a.Session.StdinPipe() 125 | if err != nil { 126 | log.Printf("get input error: %s", err.Error()) 127 | return "", "", err 128 | } 129 | //defer in.Close() 130 | 131 | var wg sync.WaitGroup 132 | wg.Add(2) 133 | 134 | errCh := make(chan error, 2) 135 | 136 | go func(in io.Writer, output *bytes.Buffer) { 137 | defer wg.Done() 138 | for { 139 | if strings.Contains(string(output.Bytes()), "[sudo] password for ") { 140 | _, err = in.Write([]byte(a.Password + "\n")) 141 | if err != nil { 142 | break 143 | } 144 | fmt.Println("put the password end.") 145 | break 146 | } 147 | } 148 | }(in, &stdOut) 149 | 150 | go func() { 151 | defer wg.Done() 152 | err = a.Session.Run(cmd) 153 | if err != nil { 154 | errCh <- err 155 | return 156 | } 157 | }() 158 | 159 | if waitTimeout(&wg, a.Timeout) { 160 | return "", "", errors.New("command timeout") 161 | } 162 | 163 | close(errCh) 164 | for err := range errCh { 165 | if err != nil { 166 | return "", "", err 167 | } 168 | } 169 | 170 | return stdOut.String(), stdErr.String(), nil 171 | } 172 | 173 | 174 | // waitTimeout waits for the waitgroup for the specified max timeout. 175 | // Returns true if waiting timed out. 176 | func waitTimeout(wg *sync.WaitGroup, timeout time.Duration) bool { 177 | c := make(chan struct{}) 178 | go func() { 179 | defer close(c) 180 | wg.Wait() 181 | }() 182 | select { 183 | case <-c: 184 | return false // completed normally 185 | case <-time.After(timeout): 186 | return true // timed out 187 | } 188 | } 189 | 190 | // Checks the response it reads from the remote, and will return a single error in case 191 | // of failure 192 | func checkResponse(r io.Reader) error { 193 | response, err := ParseResponse(r) 194 | if err != nil { 195 | return err 196 | } 197 | 198 | if response.IsFailure() { 199 | return errors.New(response.GetMessage()) 200 | } 201 | 202 | return nil 203 | } 204 | 205 | // Copies the contents of an io.Reader to a remote location 206 | func (a *Client) Copy(r io.Reader, remotePath string, permissions string, size int64) error { 207 | filename := path.Base(remotePath) 208 | 209 | wg := sync.WaitGroup{} 210 | wg.Add(2) 211 | 212 | errCh := make(chan error, 2) 213 | 214 | go func() { 215 | defer wg.Done() 216 | w, err := a.Session.StdinPipe() 217 | if err != nil { 218 | errCh <- err 219 | return 220 | } 221 | defer w.Close() 222 | 223 | stdout, err := a.Session.StdoutPipe() 224 | if err != nil { 225 | errCh <- err 226 | return 227 | } 228 | 229 | _, err = fmt.Fprintln(w, "C"+permissions, size, filename) 230 | if err != nil { 231 | errCh <- err 232 | return 233 | } 234 | 235 | if err = checkResponse(stdout); err != nil { 236 | errCh <- err 237 | return 238 | } 239 | 240 | _, err = io.Copy(w, r) 241 | if err != nil { 242 | errCh <- err 243 | return 244 | } 245 | 246 | _, err = fmt.Fprint(w, "\x00") 247 | if err != nil { 248 | errCh <- err 249 | return 250 | } 251 | 252 | if err = checkResponse(stdout); err != nil { 253 | errCh <- err 254 | return 255 | } 256 | }() 257 | 258 | go func() { 259 | defer wg.Done() 260 | err := a.Session.Run(fmt.Sprintf("%s -qt %s", a.RemoteBinary, remotePath)) 261 | if err != nil { 262 | errCh <- err 263 | return 264 | } 265 | }() 266 | 267 | if waitTimeout(&wg, a.Timeout) { 268 | return errors.New("download timeout") 269 | } 270 | 271 | close(errCh) 272 | for err := range errCh { 273 | if err != nil { 274 | return err 275 | } 276 | } 277 | return nil 278 | } 279 | 280 | func (a *Client) Close() { 281 | a.Session.Close() 282 | a.Conn.Close() 283 | } -------------------------------------------------------------------------------- /ssh/configurer.go: -------------------------------------------------------------------------------- 1 | package ssh 2 | 3 | import ( 4 | "time" 5 | 6 | "golang.org/x/crypto/ssh" 7 | ) 8 | 9 | // A struct containing all the configuration options 10 | type ClientConfigurer struct { 11 | host string 12 | clientConfig *ssh.ClientConfig 13 | timeout time.Duration 14 | remoteBinary string 15 | password string 16 | } 17 | 18 | // Creates a new client configurer. 19 | // It takes the required parameters: the host and the ssh.ClientConfig and 20 | // returns a configurer populated with the default values for the optional 21 | // parameters. 22 | // 23 | // These optional parameters can be set by using the methods provided on the 24 | // ClientConfigurer struct. 25 | func NewConfigurer(host string, config *ssh.ClientConfig) *ClientConfigurer { 26 | return &ClientConfigurer{ 27 | host: host, 28 | clientConfig: config, 29 | timeout: time.Minute, 30 | remoteBinary: "scp", 31 | password: "", 32 | } 33 | } 34 | 35 | func NewConfigurerWithBasicAuth(host, password string, config *ssh.ClientConfig) *ClientConfigurer { 36 | return &ClientConfigurer{ 37 | host: host, 38 | clientConfig: config, 39 | timeout: time.Minute, 40 | remoteBinary: "scp", 41 | password: password, 42 | } 43 | } 44 | 45 | // Sets the path of the location of the remote scp binary 46 | // Defaults to: /usr/bin/scp 47 | func (c *ClientConfigurer) RemoteBinary(path string) *ClientConfigurer { 48 | c.remoteBinary = path 49 | return c 50 | } 51 | 52 | // Alters the host of the client connects to 53 | func (c *ClientConfigurer) Host(host string) *ClientConfigurer { 54 | c.host = host 55 | return c 56 | } 57 | 58 | // Changes the connection timeout. 59 | // Defaults to one minute 60 | func (c *ClientConfigurer) Timeout(timeout time.Duration) *ClientConfigurer { 61 | c.timeout = timeout 62 | return c 63 | } 64 | 65 | // Alters the ssh.ClientConfig 66 | func (c *ClientConfigurer) ClientConfig(config *ssh.ClientConfig) *ClientConfigurer { 67 | c.clientConfig = config 68 | return c 69 | } 70 | 71 | // Builds a client with the configuration stored within the ClientConfigurer 72 | func (c *ClientConfigurer) Create() Client { 73 | return Client{ 74 | Host: c.host, 75 | ClientConfig: c.clientConfig, 76 | Timeout: c.timeout, 77 | RemoteBinary: c.remoteBinary, 78 | Password: c.password, 79 | } 80 | } -------------------------------------------------------------------------------- /ssh/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | SSH 3 | */ 4 | package ssh 5 | -------------------------------------------------------------------------------- /ssh/protocol.go: -------------------------------------------------------------------------------- 1 | package ssh 2 | 3 | import ( 4 | "bufio" 5 | "io" 6 | ) 7 | 8 | type ResponseType = uint8 9 | 10 | const ( 11 | Ok ResponseType = 0 12 | Warning ResponseType = 1 13 | Error ResponseType = 2 14 | ) 15 | 16 | // There are tree types of responses that the remote can send back: 17 | // ok, warning and error 18 | // 19 | // The difference between warning and error is that the connection is not closed by the remote, 20 | // however, a warning can indicate a file transfer failure (such as invalid destination directory) 21 | // and such be handled as such. 22 | // 23 | // All responses except for the `Ok` type always have a message (although these can be empty) 24 | // 25 | // The remote sends a confirmation after every SCP command, because a failure can occur after every 26 | // command, the response should be read and checked after sending them. 27 | type Response struct { 28 | Type ResponseType 29 | Message string 30 | } 31 | 32 | // Reads from the given reader (assuming it is the output of the remote) and parses it into a Response structure 33 | func ParseResponse(reader io.Reader) (Response, error) { 34 | buffer := make([]uint8, 1) 35 | _, err := reader.Read(buffer) 36 | if err != nil { 37 | return Response{}, err 38 | } 39 | 40 | response_type := buffer[0] 41 | message := "" 42 | if response_type > 0 { 43 | buffered_reader := bufio.NewReader(reader) 44 | message, err = buffered_reader.ReadString('\n') 45 | if err != nil { 46 | return Response{}, err 47 | } 48 | } 49 | 50 | return Response{response_type, message}, nil 51 | } 52 | 53 | func (r *Response) IsOk() bool { 54 | return r.Type == Ok 55 | } 56 | 57 | func (r *Response) IsWarning() bool { 58 | return r.Type == Warning 59 | } 60 | 61 | // Returns true when the remote responded with an error 62 | func (r *Response) IsError() bool { 63 | return r.Type == Error 64 | } 65 | 66 | // Returns true when the remote answered with a warning or an error 67 | func (r *Response) IsFailure() bool { 68 | return r.Type > 0 69 | } 70 | 71 | // Returns the message the remote sent back 72 | func (r *Response) GetMessage() string { 73 | return r.Message 74 | } -------------------------------------------------------------------------------- /ssh/ssh.go: -------------------------------------------------------------------------------- 1 | package ssh 2 | 3 | import ( 4 | "golang.org/x/crypto/ssh" 5 | "time" 6 | ) 7 | 8 | // use username and password. 9 | func NewClientWithBasicAuth(host, username, password string) Client { 10 | config, _ := PasswordKey(username, password) 11 | return NewConfigurerWithBasicAuth(host, password, &config).Create() 12 | } 13 | 14 | // user username and password with timeout 15 | func NewClientWithBasicAuthAndTimeout(host, username, password string, timeout time.Duration) Client { 16 | config, _ := PasswordKey(username, password) 17 | return NewConfigurerWithBasicAuth(host, password, &config).Timeout(timeout).Create() 18 | } 19 | 20 | // It has a default timeout of one minute. 21 | func NewClient(host string, config *ssh.ClientConfig) Client { 22 | return NewConfigurer(host, config).Create() 23 | } 24 | 25 | // Returns a new ssh.Client with provides host, ssh.ClientConfig and timeout 26 | func NewClientWithTimeout(host string, config *ssh.ClientConfig, timeout time.Duration) Client { 27 | return NewConfigurer(host, config).Timeout(timeout).Create() 28 | } -------------------------------------------------------------------------------- /ssh/ssh_test.go: -------------------------------------------------------------------------------- 1 | package ssh 2 | 3 | 4 | import ( 5 | "fmt" 6 | "os" 7 | "testing" 8 | "time" 9 | ) 10 | 11 | func TestScp(t *testing.T) { 12 | clientConfig, _ := PasswordKey("canux", "******") 13 | client := NewClient("127.0.0.1:22", &clientConfig) 14 | defer client.Close() 15 | 16 | err := client.Connect() 17 | if err != nil { 18 | t.Error("failed") 19 | } 20 | 21 | f, _ := os.Open("/home/canux/Src/go/src/github.com/crazy-canux/go-devops/data/cryptographic/APT1.yar") 22 | defer f.Close() 23 | 24 | err = client.CopyFile(f, "/home/canux/apt.yar", "0655") 25 | if err != nil { 26 | t.Error("copyfile failed") 27 | } 28 | } 29 | 30 | func TestNewClient(t *testing.T) { 31 | clientConfig, _ := PasswordKey("canux", "******") 32 | client := NewClient("127.0.0.1:22", &clientConfig) 33 | defer client.Close() 34 | 35 | err := client.Connect() 36 | if err != nil { 37 | t.Error("connection failed") 38 | } 39 | 40 | o, e, err := client.Run("pwd" ) 41 | if err != nil { 42 | t.Error("run failed") 43 | } 44 | fmt.Print(o, e) 45 | } 46 | 47 | func TestNewClientWithTimeout(t *testing.T) { 48 | clientConfig, _ := PasswordKey("canux", "******") 49 | client := NewClientWithTimeout("127.0.0.1:22", &clientConfig, time.Second * 3) 50 | defer client.Close() 51 | 52 | err := client.Connect() 53 | if err != nil { 54 | t.Error("connection failed") 55 | } 56 | 57 | o, e, err := client.Run("sleep 2" ) 58 | if err != nil { 59 | t.Errorf("run failed: %s", err.Error()) 60 | } 61 | fmt.Print(o, e) 62 | } 63 | 64 | func TestNewClientWithBasicAuth(t *testing.T) { 65 | client := NewClientWithBasicAuth("127.0.0.1:22", "canux", "******") 66 | defer client.Close() 67 | 68 | err := client.Connect() 69 | if err != nil { 70 | t.Errorf("connection failed: %s", err.Error()) 71 | } 72 | 73 | o, e, err := client.Run("pwd" ) 74 | if err != nil { 75 | t.Errorf("run failed: %s", err.Error()) 76 | } 77 | fmt.Print(o, e) 78 | } 79 | 80 | func TestNewClientWithBasicAuthAndTimeout(t *testing.T) { 81 | client := NewClientWithBasicAuthAndTimeout("127.0.0.1:22", "canux", "******", time.Second * 3) 82 | defer client.Close() 83 | 84 | err := client.Connect() 85 | if err != nil { 86 | t.Errorf("connection failed: %s", err.Error()) 87 | } 88 | 89 | o, e, err := client.Run("pwd") 90 | if err != nil { 91 | t.Errorf("run failed: %s", err.Error()) 92 | } 93 | fmt.Print(o, e) 94 | } 95 | 96 | func TestRunWithSudo(t *testing.T) { 97 | client := NewClientWithBasicAuthAndTimeout("127.0.0.1:22", "canux", "******", time.Second * 3) 98 | defer client.Close() 99 | 100 | err := client.Connect() 101 | if err != nil { 102 | t.Errorf("connection failed: %s", err.Error()) 103 | } 104 | 105 | o, e, err := client.RunWithSudo("sudo echo 1") 106 | if err != nil { 107 | t.Errorf("run with sudo failed: %s", err.Error()) 108 | } 109 | fmt.Print(o, e) 110 | } 111 | -------------------------------------------------------------------------------- /tickstack/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | # Chronograf 3 | 4 | launch with volume: 5 | 6 | $ docker run -d -p 8888:8888 \ 7 | -v chronograf-storage:/var/lib/chronograf \ 8 | chronograf:tag 9 | 10 | # Influxdb 11 | 12 | launch with volume: 13 | 14 | $ docker run -d --name=influxdb -p 8086:8086 \ 15 | -v influxdb-storage:/var/lib/influxdb \ 16 | influxdb:tag 17 | 18 | use docker network: 19 | 20 | $ docker network create influxdb 21 | 22 | $ docker run -d --name=influxdb -p 8086:8086 \ 23 | --net=influxdb 24 | influxdb:tag 25 | 26 | # Kapacitor 27 | 28 | launch with volume: 29 | 30 | $ docker run -d --name=kapacitor -p 9092:9092 \ 31 | -v kapacitor:/var/lib/kapacitor \ 32 | kapacitor:tag 33 | 34 | use localhost: 35 | 36 | $ docker run -d --name=kapacitor -p 9092:9092 \ 37 | --net=container:influxdb 38 | kapacitor:tag 39 | 40 | use configuration on node: 41 | 42 | $ docker run -d --name=kapacitor -p 9092:9092 \ 43 | -v kapacitor-storage/kapacitor.conf:/etc/kapacitor/kapacitor.conf:ro \ 44 | kapacitor:tag 45 | 46 | use docker network: 47 | 48 | [[influxdb]] 49 | urls = ["http://influxdb:8086"] 50 | 51 | # set env 52 | $ docker run -d --name=kapacitor -p 9092:9092 \ 53 | --net=influxdb \ 54 | -h kapacitor \ 55 | # This option and kapacitor config are the same. 56 | -e KAPACITOR_INFLUXDB_0_URLS_0=http://influxdb:8086 \ 57 | kapacitor:tag 58 | 59 | # Telegraf 60 | 61 | telegraf default get cpu/mem from docker not host. 62 | 63 | launch with volume: 64 | 65 | $ docker run -d --name=telegraf \ 66 | -v telegraf-storage:/var/lib/telegraf 67 | telegraf:tag 68 | 69 | use localhost: 70 | 71 | $ docker run -d --name=telegraf \ 72 | --net=container:influxdb 73 | telegraf:tag 74 | 75 | use configuration on node: 76 | 77 | $ docker run -d --name=telegraf \ 78 | -v telegraf-storage/telegraf.conf:/etc/telegraf/telegraf.conf:ro \ 79 | telegraf:tag 80 | 81 | use docker network: 82 | 83 | [[outputs.influxdb]] 84 | urls = ["http://influxdb:8086"] 85 | 86 | $ docker run -d --name=telegraf \ 87 | --net=influxdb \ 88 | -v telegraf-storage/telegraf.conf:/etc/telegraf/telegraf.conf:ro \ 89 | telegraf:tag 90 | 91 | monitoring host filesystem mount /proc: 92 | 93 | $ docker run -d --name=telegraf --restart=always \ 94 | --net=influxdb --add-host="influxdb:192.168.1.1" \ 95 | -e HOST_PROC=/home/proc \ 96 | -v /proc:/home/proc:ro \ 97 | -v telegraf-storage/telegraf.conf:/etc/telegraf/telegraf.conf:ro \ 98 | telegraf:tag 99 | 100 | monitoring other container with docker plugin: 101 | 102 | [[inputs.docker]] 103 | endpoint = "unix:///var/run/docker.sock" 104 | 105 | $ docker run -d --name=telegraf \ 106 | --net=influxdb \ 107 | -v /var/run/docker.sock:/var/run/docker.sock:ro \ 108 | -v telegraf-storage/telegraf.conf:/etc/telegraf/telegraf.conf:ro \ 109 | telegraf:tag 110 | 111 | */ 112 | package tickstack 113 | -------------------------------------------------------------------------------- /tickstack/influxdb.go: -------------------------------------------------------------------------------- 1 | package tickstack 2 | 3 | import ( 4 | "github.com/influxdata/influxdb/client/v2" 5 | "log" 6 | ) 7 | 8 | // Query from influxdb. 9 | func Query(url, measurement, ifql string) ([]string, [][]interface{}, error) { 10 | config := client.HTTPConfig{ 11 | Addr: url, 12 | } 13 | c, err := client.NewHTTPClient(config) 14 | if err != nil { 15 | log.Println("Connect failed.") 16 | return nil, nil, err 17 | } 18 | defer c.Close() 19 | 20 | q := client.Query{ 21 | Command: ifql, 22 | Database: measurement, 23 | } 24 | 25 | if response, err := c.Query(q); err == nil && response.Error() == nil { 26 | for _, result := range response.Results { 27 | for _, message := range result.Messages { 28 | log.Printf("level: %s; text: %s", message.Level, message.Text) 29 | } 30 | 31 | for _, row := range result.Series { 32 | log.Println("Name: ", row.Name) 33 | log.Println("Partial: ", row.Partial) 34 | log.Println("Tags: ", row.Tags) 35 | //for _, col := range row.Columns { 36 | // log.Println(col) 37 | //} 38 | //for _, value := range row.Values { 39 | // log.Println(value) 40 | //} 41 | return row.Columns, row.Values, nil 42 | } 43 | } 44 | } else { 45 | log.Println("Query failed.") 46 | return nil, nil, err 47 | } 48 | return nil, nil, nil 49 | } 50 | -------------------------------------------------------------------------------- /tickstack/influxdb_test.go: -------------------------------------------------------------------------------- 1 | package tickstack 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestQuery(t *testing.T) { 8 | col, val, err := Query("http://127.0.0.1:8086", "sandboxav", "select * from tail order by time desc limit 10") 9 | if err != nil { 10 | t.Error("query failed.") 11 | } else { 12 | t.Log(col) 13 | t.Log(val) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tickstack/kapacitor.go: -------------------------------------------------------------------------------- 1 | package tickstack 2 | 3 | import ( 4 | "encoding/json" 5 | "io/ioutil" 6 | "log" 7 | "net/http" 8 | ) 9 | 10 | type Response struct { 11 | Enabled bool 12 | From string 13 | Global bool 14 | Host string 15 | IdleTimeout string 16 | NoVerify bool 17 | Port int 18 | StateChangesOnly bool 19 | To []string 20 | } 21 | 22 | type SmtpResp struct { 23 | Link struct { 24 | Rel string `json:"rel"` 25 | Href string `json:"href"` 26 | } `json:"link"` 27 | Elements []struct { 28 | Link struct { 29 | Rel string `json:"rel"` 30 | Href string `json:"href"` 31 | } `json:"link"` 32 | Options struct { 33 | Enabled bool `json:"enabled"` 34 | From string `json:"from"` 35 | Global bool `json:"global"` 36 | Host string `json:"host"` 37 | IdleTimeout string `json:"idle-timeout"` 38 | NoVerify bool `json:"no-verify"` 39 | Password bool `json:"password"` 40 | Port int `json:"port"` 41 | StateChangesOnly bool `json:"state-changes-only"` 42 | To []string `json:"to"` 43 | Username string `json:"username"` 44 | } `json:"options"` 45 | Redacted []string `json:"redacted"` 46 | } `json:"elements"` 47 | } 48 | 49 | // Get smtp config from kapacitor. 50 | func GetSmtp(host, port string) (*Response, error) { 51 | var response Response 52 | url := "http://" + host + ":" + port + "/kapacitor/v1/config/smtp" 53 | 54 | res, err := http.Get(url) 55 | if err != nil { 56 | log.Println("GET smtp failed") 57 | return &response, err 58 | } 59 | body, err := ioutil.ReadAll(res.Body) 60 | res.Body.Close() 61 | if err != nil { 62 | log.Println("Read smtp failed") 63 | return &response, err 64 | } 65 | 66 | var resp SmtpResp 67 | err = json.Unmarshal(body, &resp) 68 | if err != nil { 69 | log.Println("Parse smtp failed") 70 | return &response, err 71 | } 72 | 73 | option := resp.Elements[0].Options 74 | response.Enabled = option.Enabled 75 | response.From = option.From 76 | response.Global = option.Global 77 | response.Host = option.Host 78 | response.IdleTimeout = option.IdleTimeout 79 | response.NoVerify = option.NoVerify 80 | response.Port = option.Port 81 | response.StateChangesOnly = option.StateChangesOnly 82 | response.To = option.To 83 | return &response, nil 84 | } 85 | -------------------------------------------------------------------------------- /tickstack/kapacitor_test.go: -------------------------------------------------------------------------------- 1 | package tickstack 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestGetSmtp(t *testing.T) { 8 | resp, err := GetSmtp("127.0.0.1", "9092") 9 | if err != nil { 10 | t.Error("test getsmtp failed.") 11 | } else { 12 | t.Log(resp) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /utils/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Utils for basic functions. 3 | */ 4 | package utils 5 | -------------------------------------------------------------------------------- /utils/path_walk.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "log" 5 | "os" 6 | "path/filepath" 7 | ) 8 | 9 | var files []string 10 | 11 | // Return all files with absolute path in `dir`, but exclude files in `dirEx`, and exclude file in `fileEx`. 12 | func PathWalk(dir string, dirEx, fileEx []string) ([]string, error) { 13 | err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { 14 | if err != nil { 15 | log.Printf("Processing %s failed.", info.Name()) 16 | return nil 17 | } 18 | 19 | if info.IsDir() { 20 | if In(info.Name(), dirEx) { 21 | return filepath.SkipDir 22 | } else { 23 | return nil 24 | } 25 | } 26 | 27 | if In(info.Name(), fileEx) { 28 | return nil 29 | } else { 30 | files = append(files, path) 31 | } 32 | 33 | return nil 34 | }) 35 | if err != nil { 36 | log.Println("traverse dir failed.") 37 | return files, err 38 | } 39 | return files, nil 40 | } 41 | 42 | // If `name` in `slice`, return true, else return false. 43 | func In(name string, slice []string) bool { 44 | for _, s := range slice { 45 | if name == s { 46 | return true 47 | } 48 | } 49 | return false 50 | } 51 | 52 | // If extention of `file` in list, return true, else return false. 53 | func ExtIn(file string, list []string) bool { 54 | for _, ext := range list { 55 | if filepath.Ext(file) == ext { 56 | return true 57 | } 58 | } 59 | return false 60 | } 61 | -------------------------------------------------------------------------------- /utils/path_walk_test.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | var dirExclude = []string{".git"} 9 | 10 | var fileExclude = []string{ 11 | ".gitignore", 12 | "README.txt", 13 | "auto_update.sh", 14 | "update_index.py", 15 | "update_sigs.py", 16 | "update_sigs.log", 17 | } 18 | 19 | func TestPathWalk(t *testing.T) { 20 | files, err := PathWalk("/home/canux/Documents/hastebin", dirExclude, fileExclude) 21 | if err != nil { 22 | t.Error("list dir failed.") 23 | } else { 24 | for _, f := range files { 25 | fmt.Println(f) 26 | } 27 | } 28 | } 29 | --------------------------------------------------------------------------------