Event-driven architecture ΠΏΠΎΠ²ΡΡΠ°Π΅Ρ ΡΠ΅Π½ΠΎΠ²ΡΡ ΡΡΡΠ΅ΠΊΡΠΈΠ²Π½ΠΎΡΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌΡΡ
ΡΠ΅ΡΡΡΡΠΎΠ², ΠΏΠΎΡΠΎΠΌΡ ΡΡΠΎ ΠΎΠ½ΠΈ Π·Π°Π΄Π΅ΠΉΡΡΠ²ΡΡΡΡΡ ΡΠΎΠ»ΡΠΊΠΎ Π² ΡΠΎΡ ΠΌΠΎΠΌΠ΅Π½Ρ, ΠΊΠΎΠ³Π΄Π° ΠΎΠ½ΠΈ Π½ΡΠΆΠ½Ρ. Π‘ΡΡΠ΅ΡΡΠ²ΡΠ΅Ρ ΠΌΠ°ΡΡΠ° Π²Π°ΡΠΈΠ°Π½ΡΠΎΠ², ΠΊΠ°ΠΊ ΡΡΠΎ ΡΠ΅Π°Π»ΠΈΠ·ΠΎΠ²Π°ΡΡ ΠΈ Π½Π΅ ΡΠΎΠ·Π΄Π°Π²Π°ΡΡ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΡΠ΅ ΠΎΠ±Π»Π°ΡΠ½ΡΠ΅ ΡΡΡΠ½ΠΎΡΡΠΈ Π² ΠΊΠ°ΡΠ΅ΡΡΠ²Π΅ worker-ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ. Π ΡΠ΅Π³ΠΎΠ΄Π½Ρ Ρ ΡΠ°ΡΡΠΊΠ°ΠΆΡ Π½Π΅ ΠΏΡΠΎ FaaS, Π° ΠΏΡΠΎ Π²Π΅Π±Ρ
ΡΠΊΠΈ. Π― ΠΏΠΎΠΊΠ°ΠΆΡ ΡΡΠ΅Π±Π½ΡΠΉ ΠΏΡΠΈΠΌΠ΅Ρ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ ΡΠΎΠ±ΡΡΠΈΠΉ Ρ ΠΏΠΎΠΌΠΎΡΡΡ Π²Π΅Π±Ρ
ΡΠΊΠΎΠ² ΠΎΠ±ΡΠ΅ΠΊΡΠ½ΠΎΠ³ΠΎ Ρ
ΡΠ°Π½ΠΈΠ»ΠΈΡΠ°.
ΠΠ°ΡΠ° ΡΠ»ΠΎΠ² ΠΎΠ± ΠΎΠ±ΡΠ΅ΠΊΡΠ½ΠΎΠΌ Ρ
ΡΠ°Π½ΠΈΠ»ΠΈΡΠ΅ ΠΈ ΠΎ Π²Π΅Π±Ρ
ΡΠΊΠ°Ρ
. ΠΠ±ΡΠ΅ΠΊΡΠ½ΡΠ΅ Ρ
ΡΠ°Π½ΠΈΠ»ΠΈΡΠ° ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡΡ Ρ
ΡΠ°Π½ΠΈΡΡ Π»ΡΠ±ΡΠ΅ Π΄Π°Π½Π½ΡΠ΅ Π² ΠΎΠ±Π»Π°ΠΊΠ΅ Π² Π²ΠΈΠ΄Π΅ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ², Π΄ΠΎΡΡΡΠΏΠ½ΡΡ
ΠΏΠΎ S3 ΠΈΠ»ΠΈ Π΄ΡΡΠ³ΠΎΠΌΡ API (Π² Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ ΠΎΡ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ) ΡΠ΅ΡΠ΅Π· HTTP/HTTPS. ΠΠ΅Π±Ρ
ΡΠΊΠΈ (webhooks) Π² ΠΎΠ±ΡΠ΅ΠΌ ΡΠ»ΡΡΠ°Π΅ β ΡΡΠΎ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΡΡΠΊΠΈΠ΅ ΠΎΠ±ΡΠ°ΡΠ½ΡΠ΅ Π²ΡΠ·ΠΎΠ²Ρ ΠΏΠΎ HTTP. ΠΠ±ΡΡΠ½ΠΎ ΠΎΠ½ΠΈ Π·Π°ΠΏΡΡΠΊΠ°ΡΡΡΡ ΡΠΎΠ±ΡΡΠΈΠ΅ΠΌ, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΎΡΠΏΡΠ°Π²ΠΊΠΎΠΉ ΠΊΠΎΠ΄Π° Π² ΡΠ΅ΠΏΠΎΠ·ΠΈΡΠΎΡΠΈΠΉ ΠΈΠ»ΠΈ ΠΊΠΎΠΌΠΌΠ΅Π½ΡΠ°ΡΠΈΠ΅ΠΌ, ΠΏΡΠ±Π»ΠΈΠΊΡΠ΅ΠΌΡΠΌ Π² Π±Π»ΠΎΠ³Π΅. ΠΠΎΠ³Π΄Π° ΠΏΡΠΎΠΈΡΡ
ΠΎΠ΄ΠΈΡ ΡΠΎΠ±ΡΡΠΈΠ΅, ΠΈΡΡ
ΠΎΠ΄Π½ΡΠΉ ΡΠ°ΠΉΡ ΠΎΡΠΏΡΠ°Π²Π»ΡΠ΅Ρ HTTP-Π·Π°ΠΏΡΠΎΡ Π½Π° URL-Π°Π΄ΡΠ΅Ρ, ΡΠΊΠ°Π·Π°Π½Π½ΡΠΉ Π΄Π»Ρ Π²Π΅Π±Ρ
ΡΠΊΠ°. Π ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠ΅ ΠΌΠΎΠΆΠ½ΠΎ ΡΠ΄Π΅Π»Π°ΡΡ ΡΠ°ΠΊ, ΡΡΠΎΠ±Ρ ΡΠΎΠ±ΡΡΠΈΡ Π½Π° ΠΎΠ΄Π½ΠΎΠΌ ΡΠ°ΠΉΡΠ΅ Π²ΡΠ·ΡΠ²Π°Π»ΠΈ Π΄Π΅ΠΉΡΡΠ²ΠΈΡ Π½Π° Π΄ΡΡΠ³ΠΎΠΌ (
ΠΡΠΈΠΌΠ΅ΡΡ ΠΏΡΠΎΡΡΡΡ ΠΊΠ΅ΠΉΡΠΎΠ², ΠΊΠΎΠ³Π΄Π° ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΡΠ°ΠΊΡΡ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΠ·Π°ΡΠΈΡ:
- Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΊΠΎΠΏΠΈΠΉ Π²ΡΠ΅Ρ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ² Π² Π΄ΡΡΠ³ΠΎΠΌ ΠΎΠ±Π»Π°ΡΠ½ΠΎΠΌ Ρ ΡΠ°Π½ΠΈΠ»ΠΈΡΠ΅. ΠΠΎΠΏΠΈΠΈ Π΄ΠΎΠ»ΠΆΠ½Ρ ΡΠΎΠ·Π΄Π°Π²Π°ΡΡΡΡ Β«Π½Π° Π»Π΅ΡΡΒ», ΠΏΡΠΈ Π»ΡΠ±ΠΎΠΌ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠΈ ΠΈΠ»ΠΈ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΈ ΡΠ°ΠΉΠ»ΠΎΠ².
- ΠΠ²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΎΠ΅ ΡΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΡΠ΅ΡΠΈΠΉ ΠΌΠΈΠ½ΠΈΠ°ΡΡΡ Π³ΡΠ°ΡΠΈΡΠ΅ΡΠΊΠΈΡ ΡΠ°ΠΉΠ»ΠΎΠ², Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ Π²ΠΎΠ΄ΡΠ½ΡΡ Π·Π½Π°ΠΊΠΎΠ² ΠΊ ΡΠΎΡΠΎΠ³ΡΠ°ΡΠΈΡΠΌ, Π΄ΡΡΠ³ΠΈΠ΅ ΠΌΠΎΠ΄ΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠΉ.
- ΠΠΏΠΎΠ²Π΅ΡΠ΅Π½ΠΈΠ΅ ΠΎ ΠΏΡΠΈΡ ΠΎΠ΄Π΅ Π½ΠΎΠ²ΡΡ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠΎΠ² (ΠΊ ΠΏΡΠΈΠΌΠ΅ΡΡ, ΡΠ°ΡΠΏΡΠ΅Π΄Π΅Π»Π΅Π½Π½Π°Ρ Π±ΡΡ Π³Π°Π»ΡΠ΅ΡΡΠΊΠ°Ρ ΡΠ»ΡΠΆΠ±Π° Π²ΡΠΊΠ»Π°Π΄ΡΠ²Π°Π΅Ρ Π² ΠΎΠ±Π»Π°ΠΊΠΎ ΠΎΡΡΠ΅ΡΡ, Π° ΡΠΈΠ½ΠΌΠΎΠ½ΠΈΡΠΎΡΠΈΠ½Π³ ΠΏΠΎΠ»ΡΡΠ°Π΅Ρ ΠΎΠΏΠΎΠ²Π΅ΡΠ΅Π½ΠΈΡ ΠΎ Π½ΠΎΠ²ΡΡ ΠΎΡΡΠ΅ΡΠ°Ρ , ΠΏΡΠΎΠ²Π΅ΡΡΠ΅Ρ ΠΈ Π°Π½Π°Π»ΠΈΠ·ΠΈΡΡΠ΅Ρ ΠΈΡ ).
- Π§ΡΡΡ Π±ΠΎΠ»Π΅Π΅ ΡΠ»ΠΎΠΆΠ½ΡΠ΅ ΠΊΠ΅ΠΉΡΡ ΠΏΠΎΠ΄ΡΠ°Π·ΡΠΌΠ΅Π²Π°ΡΡ, ΠΊ ΠΏΡΠΈΠΌΠ΅ΡΡ, ΡΠΎΡΠΌΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ Π·Π°ΠΏΡΠΎΡΠ° ΠΊ Kubernetes, ΠΊΠΎΡΠΎΡΡΠΉ ΡΠΎΠ·Π΄Π°Π΅Ρ ΠΏΠΎΠ΄ Ρ Π½ΡΠΆΠ½ΡΠΌΠΈ ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅ΡΠ°ΠΌΠΈ, ΠΏΠ΅ΡΠ΅Π΄Π°Π΅Ρ Π² Π½Π΅Π³ΠΎ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ Π·Π°Π΄Π°ΡΠΈ ΠΈ ΠΏΠΎΡΠ»Π΅ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ ΡΠ²ΠΎΡΠ°ΡΠΈΠ²Π°Π΅Ρ ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅Ρ.
Π ΠΊΠ°ΡΠ΅ΡΡΠ²Π΅ ΠΏΡΠΈΠΌΠ΅ΡΠ° ΠΌΡ ΡΠ΄Π΅Π»Π°Π΅ΠΌ Π²Π°ΡΠΈΠ°Π½Ρ Π·Π°Π΄Π°ΡΠΈ 1, ΠΊΠΎΠ³Π΄Π° ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΡ Π² Π±Π°ΠΊΠ΅ΡΠ΅ ΠΎΠ±ΡΠ΅ΠΊΡΠ½ΠΎΠ³ΠΎ Ρ ΡΠ°Π½ΠΈΠ»ΠΈΡΠ° Mail.ru Cloud Solutions (MCS) Ρ ΠΏΠΎΠΌΠΎΡΡΡ Π²Π΅Π±Ρ ΡΠΊΠΎΠ² ΡΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·ΠΈΡΡΡΡΡΡ Π² ΠΎΠ±ΡΠ΅ΠΊΡΠ½ΠΎΠΌ Ρ ΡΠ°Π½ΠΈΠ»ΠΈΡΠ΅ AWS. Π ΡΠ΅Π°Π»ΡΠ½ΠΎΠΌ Π½Π°Π³ΡΡΠΆΠ΅Π½Π½ΠΎΠΌ ΠΊΠ΅ΠΉΡΠ΅ ΡΠ»Π΅Π΄ΡΠ΅Ρ ΠΏΡΠ΅Π΄ΡΡΠΌΠΎΡΡΠ΅ΡΡ Π°ΡΠΈΠ½Ρ ΡΠΎΠ½Π½ΡΡ ΡΠ°Π±ΠΎΡΡ Π·Π° ΡΡΠ΅Ρ ΡΠ΅Π³ΠΈΡΡΡΠ°ΡΠΈΠΈ Π²Π΅Π±Ρ ΡΠΊΠΎΠ² Π² ΠΎΡΠ΅ΡΠ΅Π΄ΠΈ, Π½ΠΎ Π΄Π»Ρ ΡΡΠ΅Π±Π½ΠΎΠΉ Π·Π°Π΄Π°ΡΠΈ ΠΌΡ ΡΠ΄Π΅Π»Π°Π΅ΠΌ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ Π±Π΅Π· ΡΡΠΎΠ³ΠΎ.
Π‘Ρ Π΅ΠΌΠ° ΡΠ°Π±ΠΎΡΡ
ΠΡΠΎΡΠΎΠΊΠΎΠ» Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΠΈΡ Π΄Π΅ΡΠ°Π»ΡΠ½ΠΎ ΠΎΠΏΠΈΡΠ°Π½ Π²
- Π‘Π΅ΡΠ²ΠΈΡ ΠΏΡΠ±Π»ΠΈΠΊΠ°ΡΠΈΠΈ, ΠΊΠΎΡΠΎΡΡΠΉ Π½Π°Ρ ΠΎΠ΄ΠΈΡΡΡ Π½Π° ΡΡΠΎΡΠΎΠ½Π΅ S3-Ρ ΡΠ°Π½ΠΈΠ»ΠΈΡΠ° ΠΈ ΠΏΡΠ±Π»ΠΈΠΊΡΠ΅Ρ HTTP-Π·Π°ΠΏΡΠΎΡΡ ΠΏΡΠΈ ΡΡΠ°Π±Π°ΡΡΠ²Π°Π½ΠΈΠΈ webnhook.
- Π‘Π΅ΡΠ²Π΅Ρ ΠΏΡΠΈΠ΅ΠΌΠ° Π²Π΅Π±Ρ ΡΠΊΠΎΠ², ΠΊΠΎΡΠΎΡΡΠΉ ΡΠ»ΡΡΠ°Π΅Ρ ΠΎΠ±ΡΠ°ΡΠ΅Π½ΠΈΡ ΡΠ΅ΡΠ²ΠΈΡΠ° ΠΏΡΠ±Π»ΠΈΠΊΠ°ΡΠΈΠΈ ΠΏΠΎ HTTP ΠΈ Π²ΡΠΏΠΎΠ»Π½ΡΠ΅Ρ ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΡΡΠΈΠ΅ Π΄Π΅ΠΉΡΡΠ²ΠΈΡ. Π‘Π΅ΡΠ²Π΅Ρ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ Π½Π°ΠΏΠΈΡΠ°Π½ Π½Π° Π»ΡΠ±ΠΎΠΌ ΡΠ·ΡΠΊΠ΅, Π² Π½Π°ΡΠ΅ΠΌ ΠΏΡΠΈΠΌΠ΅ΡΠ΅ ΠΌΡ Π½Π°ΠΏΠΈΡΠ΅ΠΌ ΡΠ΅ΡΠ²Π΅Ρ Π½Π° Go.
ΠΡΠΎΠ±Π΅Π½Π½ΠΎΡΡΡ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ Π²Π΅Π±Ρ ΡΠΊΠΎΠ² Π² S3 API β ΡΠ΅Π³ΠΈΡΡΡΠ°ΡΠΈΡ ΡΠ΅ΡΠ²Π΅ΡΠ° ΠΏΡΠΈΠ΅ΠΌΠ° Π²Π΅Π±Ρ ΡΠΊΠΎΠ² Π½Π° ΡΠ΅ΡΠ²ΠΈΡΠ΅ ΠΏΡΠ±Π»ΠΈΠΊΠ°ΡΠΈΠΈ. Π ΡΠ°ΡΡΠ½ΠΎΡΡΠΈ, ΡΠ΅ΡΠ²Π΅Ρ ΠΏΡΠΈΠ΅ΠΌΠ° Π²Π΅Π±Ρ ΡΠΊΠΎΠ² Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΏΠΎΠ΄ΡΠ²Π΅ΡΠ΄ΠΈΡΡ ΠΏΠΎΠ΄ΠΏΠΈΡΠΊΡ Π½Π° ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ ΡΠ΅ΡΠ²ΠΈΡΠ° ΠΏΡΠ±Π»ΠΈΠΊΠ°ΡΠΈΠΈ (Π² Π΄ΡΡΠ³ΠΈΡ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡΡ Π²Π΅Π±Ρ ΡΠΊΠΎΠ² ΠΎΠ±ΡΡΠ½ΠΎ ΠΏΠΎΠ΄ΡΠ²Π΅ΡΠΆΠ΄Π°ΡΡ ΠΏΠΎΠ΄ΠΏΠΈΡΠΊΡ Π½Π΅ ΡΡΠ΅Π±ΡΠ΅ΡΡΡ).
Π‘ΠΎΠΎΡΠ²Π΅ΡΡΡΠ²Π΅Π½Π½ΠΎ, ΡΠ΅ΡΠ²Π΅Ρ ΠΏΡΠΈΠ΅ΠΌΠ° Π²Π΅Π±Ρ ΡΠΊΠΎΠ² Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°ΡΡ Π΄Π²Π΅ ΠΎΡΠ½ΠΎΠ²Π½ΡΡ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ:
- ΠΎΡΠ²Π΅ΡΠ°ΡΡ Π½Π° Π·Π°ΠΏΡΠΎΡ ΡΠ΅ΡΠ²ΠΈΡΠ° ΠΏΡΠ±Π»ΠΈΠΊΠ°ΡΠΈΠΈ ΠΎ ΠΏΠΎΠ΄ΡΠ²Π΅ΡΠΆΠ΄Π΅Π½ΠΈΠΈ ΡΠ΅Π³ΠΈΡΡΡΠ°ΡΠΈΠΈ,
- ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°ΡΡ ΠΏΡΠΈΡ ΠΎΠ΄ΡΡΠΈΠ΅ ΡΠΎΠ±ΡΡΠΈΡ.
Π£ΡΡΠ°Π½ΠΎΠ²ΠΊΠ° ΡΠ΅ΡΠ²Π΅ΡΠ° ΠΏΡΠΈΠ΅ΠΌΠ° Π²Π΅Π±Ρ ΡΠΊΠΎΠ²
ΠΠ»Ρ Π·Π°ΠΏΡΡΠΊΠ° ΡΠ΅ΡΠ²Π΅ΡΠ° ΠΏΡΠΈΠ΅ΠΌΠ° Π²Π΅Π±Ρ ΡΠΊΠΎΠ² Π½ΡΠΆΠ΅Π½ Linux-ΡΠ΅ΡΠ²Π΅Ρ. Π Π΄Π°Π½Π½ΠΎΠΉ ΡΡΠ°ΡΡΠ΅ Π΄Π»Ρ ΠΏΡΠΈΠΌΠ΅ΡΠ° ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌ Π²ΠΈΡΡΡΠ°Π»ΡΠ½ΡΠΉ ΠΈΠ½ΡΡΠ°Π½Ρ, ΠΊΠΎΡΠΎΡΡΠΉ ΡΠ°Π·Π²Π΅ΡΡΡΠ²Π°Π΅ΠΌ Π½Π° MCS.
Π£ΡΡΠ°Π½ΠΎΠ²ΠΈΠΌ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎΠ΅ ΠΠ ΠΈ Π·Π°ΠΏΡΡΡΠΈΠΌ ΡΠ΅ΡΠ²Π΅Ρ ΠΏΡΠΈΠ΅ΠΌΠ° Π²Π΅Π±Ρ ΡΠΊΠΎΠ².
ubuntu@ubuntu-basic-1-2-10gb:~$ sudo apt-get install git
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages were automatically installed and are no longer required:
bc dns-root-data dnsmasq-base ebtables landscape-common liblxc-common
liblxc1 libuv1 lxcfs lxd lxd-client python3-attr python3-automat
python3-click python3-constantly python3-hyperlink
python3-incremental python3-pam python3-pyasn1-modules
python3-service-identity python3-twisted python3-twisted-bin
python3-zope.interface uidmap xdelta3
Use 'sudo apt autoremove' to remove them.
Suggested packages:
git-daemon-run | git-daemon-sysvinit git-doc git-el git-email git-gui
gitk gitweb git-cvs git-mediawiki git-svn
The following NEW packages will be installed:
git
0 upgraded, 1 newly installed, 0 to remove and 46 not upgraded.
Need to get 3915 kB of archives.
After this operation, 32.3 MB of additional disk space will be used.
Get:1 http://MS1.clouds.archive.ubuntu.com/ubuntu bionic-updates/main
amd64 git amd64 1:2.17.1-1ubuntu0.7 [3915 kB]
Fetched 3915 kB in 1s (5639 kB/s)
Selecting previously unselected package git.
(Reading database ... 53932 files and directories currently installed.)
Preparing to unpack .../git_1%3a2.17.1-1ubuntu0.7_amd64.deb ...
Unpacking git (1:2.17.1-1ubuntu0.7) ...
Setting up git (1:2.17.1-1ubuntu0.7) ...
ΠΠ»ΠΎΠ½ΠΈΡΡΠ΅ΠΌ ΠΏΠ°ΠΏΠΊΡ Ρ ΡΠ΅ΡΠ²Π΅ΡΠΎΠΌ ΠΏΡΠΈΠ΅ΠΌΠ° Π²Π΅Π±Ρ ΡΠΊΠΎΠ²:
ubuntu@ubuntu-basic-1-2-10gb:~$ git clone
https://github.com/RomanenkoDenys/s3-webhook.git
Cloning into 's3-webhook'...
remote: Enumerating objects: 48, done.
remote: Counting objects: 100% (48/48), done.
remote: Compressing objects: 100% (27/27), done.
remote: Total 114 (delta 20), reused 45 (delta 18), pack-reused 66
Receiving objects: 100% (114/114), 23.77 MiB | 20.25 MiB/s, done.
Resolving deltas: 100% (49/49), done.
ΠΠ°ΠΏΡΡΡΠΈΠΌ ΡΠ΅ΡΠ²Π΅Ρ:
ubuntu@ubuntu-basic-1-2-10gb:~$ cd s3-webhook/
ubuntu@ubuntu-basic-1-2-10gb:~/s3-webhook$ sudo ./s3-webhook -port 80
ΠΠΎΠ΄ΠΏΠΈΡΠΊΠ° Π½Π° ΡΠ΅ΡΠ²ΠΈΡ ΠΏΡΠ±Π»ΠΈΠΊΠ°ΡΠΈΠΈ
ΠΠ°ΡΠ΅Π³ΠΈΡΡΡΠΈΡΠΎΠ²Π°ΡΡ ΡΠ²ΠΎΠΉ ΡΠ΅ΡΠ²Π΅Ρ ΠΏΡΠΈΠ΅ΠΌΠ° Π²Π΅Π±Ρ ΡΠΊΠΎΠ² ΠΌΠΎΠΆΠ½ΠΎ ΡΠ΅ΡΠ΅Π· API Π»ΠΈΠ±ΠΎ web-ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ. ΠΠ»Ρ ΠΏΡΠΎΡΡΠΎΡΡ Π±ΡΠ΄Π΅ΠΌ ΡΠ΅Π³ΠΈΡΡΡΠΈΡΠΎΠ²Π°ΡΡ ΡΠ΅ΡΠ΅Π· web-ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ:
ΠΠ΄Π΅ΠΌ Π² ΡΠ°Π·Π΄Π΅Π» Π±Π°ΠΊΠ΅ΡΠΎΠ² Π² ΠΊΠ°Π±ΠΈΠ½Π΅ΡΠ΅ ΡΠΏΡΠ°Π²Π»Π΅Π½ΠΈΡ.- ΠΠ°Ρ ΠΎΠ΄ΠΈΠΌ Π² Π±Π°ΠΊΠ΅Ρ, Π΄Π»Ρ ΠΊΠΎΡΠΎΡΠΎΠ³ΠΎ Π±ΡΠ΄Π΅ΠΌ Π½Π°ΡΡΡΠ°ΠΈΠ²Π°ΡΡ wΠ΅bhooks, ΠΈ Π½Π°ΠΆΠΈΠΌΠ°Π΅ΠΌ Π½Π° ΡΠ΅ΡΡΠ΅ΡΠ΅Π½ΠΊΡ:
ΠΠ΅ΡΠ΅Ρ
ΠΎΠ΄ΠΈΠΌ Π½Π° Π²ΠΊΠ»Π°Π΄ΠΊΡ Webhooks ΠΈ Π½Π°ΠΆΠΈΠΌΠ°Π΅ΠΌ ΠΠΎΠ±Π°Π²ΠΈΡΡ:
ΠΠ°ΠΏΠΎΠ»Π½ΡΠ΅ΠΌ ΠΏΠΎΠ»Ρ:
ID β Π½Π°Π·Π²Π°Π½ΠΈΠ΅ Π²Π΅Π±Ρ
ΡΠΊΠ°.
Event β ΠΊΠ°ΠΊΠΈΠ΅ ΡΠΎΠ±ΡΡΠΈΡ ΠΏΠ΅ΡΠ΅Π΄Π°Π²Π°ΡΡ. ΠΡ Π·Π°Π΄Π°Π»ΠΈ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡ Π²ΡΠ΅Ρ ΡΠΎΠ±ΡΡΠΈΠΉ, ΠΊΠΎΡΠΎΡΡΠ΅ ΠΏΡΠΎΠΈΡΡ ΠΎΠ΄ΡΡ ΠΏΡΠΈ ΡΠ°Π±ΠΎΡΠ΅ Ρ ΡΠ°ΠΉΠ»Π°ΠΌΠΈ (Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΈ ΡΠ΄Π°Π»Π΅Π½ΠΈΠ΅).
URL β Π°Π΄ΡΠ΅Ρ ΡΠ΅ΡΠ²Π΅ΡΠ° ΠΏΡΠΈΠ΅ΠΌΠ° Π²Π΅Π±Ρ ΡΠΊΠΎΠ².
Filter prefix/suffix β ΡΠΈΠ»ΡΡΡ, ΠΊΠΎΡΠΎΡΡΠΉ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ Π³Π΅Π½Π΅ΡΠΈΡΠΎΠ²Π°ΡΡ Π²Π΅Π±Ρ ΡΠΊΠΈ ΡΠΎΠ»ΡΠΊΠΎ Π½Π° ΠΎΠ±ΡΠ΅ΠΊΡΡ, Π½Π°Π·Π²Π°Π½ΠΈΡ ΠΊΠΎΡΠΎΡΡΡ ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΡΡ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½Π½ΡΠΌ ΠΏΡΠ°Π²ΠΈΠ»Π°ΠΌ. ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, ΡΡΠΎΠ±Ρ Π²Π΅Π±Ρ ΡΠΊ ΡΡΠ°Π±Π°ΡΡΠ²Π°Π» ΡΠΎΠ»ΡΠΊΠΎ ΡΠ°ΠΉΠ»Ρ Ρ ΡΠ°ΡΡΠΈΡΠ΅Π½ΠΈΠ΅ΠΌ .png, Π² Filter suffix Π½Π°Π΄ΠΎ Π½Π°ΠΏΠΈΡΠ°ΡΡ Β«pngΒ».
Π ΡΠ΅ΠΊΡΡΠΈΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°ΡΡΡΡ Π΄Π»Ρ ΠΎΠ±ΡΠ°ΡΠ΅Π½ΠΈΡ ΠΊ ΡΠ΅ΡΠ²Π΅ΡΡ ΠΏΡΠΈΠ΅ΠΌΠ° Π²Π΅Π±Ρ ΡΠΊΠΎΠ² ΡΠΎΠ»ΡΠΊΠΎ ΠΏΠΎΡΡΡ 80 ΠΈ 443.
ΠΠ°ΠΆΠΌΠ΅ΠΌ ΠΠΎΠ±Π°Π²ΠΈΡΡ hook ΠΈ ΡΠ²ΠΈΠ΄ΠΈΠΌ ΡΠ»Π΅Π΄ΡΡΡΠ΅Π΅:
Hook Π΄ΠΎΠ±Π°Π²Π»Π΅Π½.
Π‘Π΅ΡΠ²Π΅Ρ ΠΏΡΠΈΠ΅ΠΌΠ° Π²Π΅Π±Ρ ΡΠΊΠΎΠ² Π² Π»ΠΎΠ³Π°Ρ ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°Π΅Ρ ΠΏΡΠΎΡ ΠΎΠΆΠ΄Π΅Π½ΠΈΠ΅ ΠΏΡΠΎΡΠ΅ΡΡΠ° ΡΠ΅Π³ΠΈΡΡΡΠ°ΡΠΈΠΈ Ρ ΡΠΊΠ°:
ubuntu@ubuntu-basic-1-2-10gb:~/s3-webhook$ sudo ./s3-webhook -port 80
2020/06/15 12:01:14 [POST] incoming HTTP request from
95.163.216.92:42530
2020/06/15 12:01:14 Got timestamp: 2020-06-15T15:01:13+03:00 TopicArn:
mcs5259999770|myfiles-ash|s3:ObjectCreated:*,s3:ObjectRemoved:* Token:
E2itMqAMUVVZc51pUhFWSp13DoxezvRxkUh5P7LEuk1dEe9y URL:
http://89.208.199.220/webhook
2020/06/15 12:01:14 Generate responce signature:
3754ce36636f80dfd606c5254d64ecb2fd8d555c27962b70b4f759f32c76b66d
Π Π΅Π³ΠΈΡΡΡΠ°ΡΠΈΡ Π·Π°ΠΊΠΎΠ½ΡΠ΅Π½Π°. Π ΡΠ»Π΅Π΄ΡΡΡΠ΅ΠΌ ΡΠ°Π·Π΄Π΅Π»Π΅ Π±ΠΎΠ»Π΅Π΅ Π΄Π΅ΡΠ°Π»ΡΠ½ΠΎ ΡΠ°ΡΡΠΌΠΎΡΡΠΈΠΌ Π°Π»Π³ΠΎΡΠΈΡΠΌ ΡΠ°Π±ΠΎΡΡ ΡΠ΅ΡΠ²Π΅ΡΠ° ΠΏΡΠΈΠ΅ΠΌΠ° Π²Π΅Π±Ρ ΡΠΊΠΎΠ².
ΠΠΏΠΈΡΠ°Π½ΠΈΠ΅ ΡΠ΅ΡΠ²Π΅ΡΠ° ΠΏΡΠΈΠ΅ΠΌΠ° Π²Π΅Π±Ρ ΡΠΊΠΎΠ²
Π Π½Π°ΡΠ΅ΠΌ ΠΏΡΠΈΠΌΠ΅ΡΠ΅ ΡΠ΅ΡΠ²Π΅Ρ Π½Π°ΠΏΠΈΡΠ°Π½ Π½Π° Go. Π Π°Π·Π±Π΅ΡΠ΅ΠΌ ΠΎΡΠ½ΠΎΠ²Π½ΡΠ΅ ΠΏΡΠΈΠ½ΡΠΈΠΏΡ Π΅Π³ΠΎ ΡΠ°Π±ΠΎΡΡ.
package main
// Generate hmac_sha256_hex
func HmacSha256hex(message string, secret string) string {
}
// Generate hmac_sha256
func HmacSha256(message string, secret string) string {
}
// Send subscription confirmation
func SubscriptionConfirmation(w http.ResponseWriter, req *http.Request, body []byte) {
}
// Send subscription confirmation
func GotRecords(w http.ResponseWriter, req *http.Request, body []byte) {
}
// Liveness probe
func Ping(w http.ResponseWriter, req *http.Request) {
// log request
log.Printf("[%s] incoming HTTP Ping request from %sn", req.Method, req.RemoteAddr)
fmt.Fprintf(w, "Pongn")
}
//Webhook
func Webhook(w http.ResponseWriter, req *http.Request) {
}
func main() {
// get command line args
bindPort := flag.Int("port", 80, "number between 1-65535")
bindAddr := flag.String("address", "", "ip address in dot format")
flag.StringVar(&actionScript, "script", "", "external script to execute")
flag.Parse()
http.HandleFunc("/ping", Ping)
http.HandleFunc("/webhook", Webhook)
log.Fatal(http.ListenAndServe(*bindAddr+":"+strconv.Itoa(*bindPort), nil))
}
Π Π°ΡΡΠΌΠΎΡΡΠΈΠΌ ΠΎΡΠ½ΠΎΠ²Π½ΡΠ΅ ΡΡΠ½ΠΊΡΠΈΠΈ:
- Ping() β ΡΠΎΡΡ, ΠΎΡΠ²Π΅ΡΠ°ΡΡΠΈΠΉ ΠΏΠΎ URL/ping, ΠΏΡΠΎΡΡΠ΅ΠΉΡΠ°Ρ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ liveness probe.
- Webhook() β ΠΎΡΠ½ΠΎΠ²Π½ΠΎΠΉ ΡΠΎΡΡ, ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ URL/Π²Π΅Π±Ρ
ΡΠΊΠ°:
- ΠΏΠΎΠ΄ΡΠ²Π΅ΡΠΆΠ΄Π°Π΅Ρ ΡΠ΅Π³ΠΈΡΡΡΠ°ΡΠΈΡ Π½Π° ΡΠ΅ΡΠ²ΠΈΡΠ΅ ΠΏΡΠ±Π»ΠΈΠΊΠ°ΡΠΈΠΈ (ΠΏΠ΅ΡΠ΅Ρ ΠΎΠ΄ Π² ΡΡΠ½ΠΊΡΠΈΡ SubscriptionConfirmation),
- ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°Π΅Ρ ΠΏΡΠΈΡ ΠΎΠ΄ΡΡΠΈΠ΅ Π²Π΅Π±Ρ ΡΠΊΠΈ (ΡΡΠ½ΠΊΡΠΈΡ Gotrecords).
- Π€ΡΠ½ΠΊΡΠΈΠΈ HmacSha256 ΠΈ HmacSha256hex β ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ Π°Π»Π³ΠΎΡΠΈΡΠΌΠΎΠ² ΡΠΈΡΡΠΎΠ²Π°Π½ΠΈΡ HMAC-SHA256 ΠΈ HMAC-SHA256 Ρ Π²ΡΠ²ΠΎΠ΄ΠΎΠΌ Π² Π²ΠΈΠ΄Π΅ ΡΡΡΠΎΠΊΠΈ 16-ΡΠΈΡΠ½ΡΡ ΡΠΈΡΠ΅Π» Π΄Π»Ρ ΠΏΠΎΠ΄ΡΡΡΠ΅ΡΠ° ΡΠΈΠ³Π½Π°ΡΡΡΡ.
- main β Π³Π»Π°Π²Π½Π°Ρ ΡΡΠ½ΠΊΡΠΈΡ, ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°Π΅Ρ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠΉ ΡΡΡΠΎΠΊΠΈ ΠΈ ΡΠ΅Π³ΠΈΡΡΡΠΈΡΡΠ΅Ρ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΈ URL.
ΠΠ°ΡΠ°ΠΌΠ΅ΡΡΡ ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠΉ ΡΡΡΠΎΠΊΠΈ, ΠΏΡΠΈΠ½ΠΈΠΌΠ°Π΅ΠΌΡΠ΅ ΡΠ΅ΡΠ²Π΅ΡΠΎΠΌ:
- -port β ΠΏΠΎΡΡ, Π½Π° ΠΊΠΎΡΠΎΡΠΎΠΌ ΡΠ΅ΡΠ²Π΅Ρ Π±ΡΠ΄Π΅Ρ ΡΠ»ΡΡΠ°ΡΡ.
- -address β IP-Π°Π΄ΡΠ΅Ρ, ΠΊΠΎΡΠΎΡΡΠΉ Π±ΡΠ΄Π΅Ρ ΡΠ»ΡΡΠ°ΡΡ ΡΠ΅ΡΠ²Π΅Ρ.
- -script β Π²Π½Π΅ΡΠ½ΡΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ°, ΠΊΠΎΡΠΎΡΠ°Ρ Π²ΡΠ·ΡΠ²Π°Π΅ΡΡΡ Π½Π° ΠΊΠ°ΠΆΠ΄ΡΠΉ ΠΏΡΠΈΡΠ΅Π΄ΡΠΈΠΉ Ρ ΡΠΊ.
Π Π°ΡΡΠΌΠΎΡΡΠΈΠΌ ΠΏΠΎΠ΄ΡΠΎΠ±Π½Π΅Π΅ Π½Π΅ΠΊΠΎΡΠΎΡΡΠ΅ ΡΡΠ½ΠΊΡΠΈΠΈ:
//Webhook
func Webhook(w http.ResponseWriter, req *http.Request) {
// Read body
body, err := ioutil.ReadAll(req.Body)
defer req.Body.Close()
if err != nil {
http.Error(w, err.Error(), 500)
return
}
// log request
log.Printf("[%s] incoming HTTP request from %sn", req.Method, req.RemoteAddr)
// check if we got subscription confirmation request
if strings.Contains(string(body),
""Type":"SubscriptionConfirmation"") {
SubscriptionConfirmation(w, req, body)
} else {
GotRecords(w, req, body)
}
}
ΠΡΠ° ΡΡΠ½ΠΊΡΠΈΡ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΠ΅Ρ, ΡΡΠΎ ΠΏΡΠΈΡΠ»ΠΎ β Π·Π°ΠΏΡΠΎΡ Π½Π° ΠΏΠΎΠ΄ΡΠ²Π΅ΡΠΆΠ΄Π΅Π½ΠΈΠ΅ ΡΠ΅Π³ΠΈΡΡΡΠ°ΡΠΈΠΈ Π»ΠΈΠ±ΠΎ Π²Π΅Π±Ρ
ΡΠΊ. ΠΠ°ΠΊ ΡΠ»Π΅Π΄ΡΠ΅Ρ ΠΈΠ·
POST http://test.com HTTP/1.1
x-amz-sns-messages-type: SubscriptionConfirmation
content-type: application/json
{
"Timestamp":"2019-12-26T19:29:12+03:00",
"Type":"SubscriptionConfirmation",
"Message":"You have chosen to subscribe to the topic $topic. To confirm the subscription you need to response with calculated signature",
"TopicArn":"mcs2883541269|bucketA|s3:ObjectCreated:Put",
"SignatureVersion":1,
"Token":Β«RPE5UuG94rGgBH6kHXN9FUPugFxj1hs2aUQc99btJp3E49tAΒ»
}
ΠΠ° ΡΡΠΎΡ Π·Π°ΠΏΡΠΎΡ Π½ΡΠΆΠ½ΠΎ ΠΎΡΠ²Π΅ΡΠΈΡΡ:
content-type: application/json
{"signature":Β«ea3fce4bb15c6de4fec365d36bcebbc34ccddf54616d5ca12e1972f82b6d37afΒ»}
ΠΠ΄Π΅ ΡΠΈΠ³Π½Π°ΡΡΡΠ° Π²ΡΡΠΈΡΠ»ΡΠ΅ΡΡΡ ΠΊΠ°ΠΊ:
signature = hmac_sha256(url, hmac_sha256(TopicArn,
hmac_sha256(Timestamp, Token)))
POST <url> HTTP/1.1
x-amz-sns-messages-type: SubscriptionConfirmation
{ "Records":
[
{
"s3": {
"object": {
"eTag":"aed563ecafb4bcc5654c597a421547b2",
"sequencer":1577453615,
"key":"some-file-to-bucket",
"size":100
},
"configurationId":"1",
"bucket": {
"name": "bucketA",
"ownerIdentity": {
"principalId":"mcs2883541269"}
},
"s3SchemaVersion":"1.0"
},
"eventVersion":"1.0",
"requestParameters":{
"sourceIPAddress":"185.6.245.156"
},
"userIdentity": {
"principalId":"2407013e-cbc1-415f-9102-16fb9bd6946b"
},
"eventName":"s3:ObjectCreated:Put",
"awsRegion":"ru-msk",
"eventSource":"aws:s3",
"responseElements": {
"x-amz-request-id":"VGJR5rtJ"
}
}
]
}
Π‘ΠΎΠΎΡΠ²Π΅ΡΡΡΠ²Π΅Π½Π½ΠΎ, Π² Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ ΠΎΡ Π·Π°ΠΏΡΠΎΡΠ° Π½ΡΠΆΠ½ΠΎ ΠΏΠΎΠ½ΡΡΡ, ΠΊΠ°ΠΊ ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°ΡΡ Π΄Π°Π½Π½ΡΠ΅. Π― Π²ΡΠ±ΡΠ°Π» Π² ΠΊΠ°ΡΠ΅ΡΡΠ²Π΅ ΠΈΠ½Π΄ΠΈΠΊΠ°ΡΠΎΡΠ° Π·Π°ΠΏΠΈΡΡ "Type":"SubscriptionConfirmation"
, ΠΏΠΎΡΠΊΠΎΠ»ΡΠΊΡ ΠΎΠ½Π° ΠΏΡΠΈΡΡΡΡΡΠ²ΡΠ΅Ρ Π² Π·Π°ΠΏΡΠΎΡΠ΅ Π½Π° ΠΏΠΎΠ΄ΡΠ²Π΅ΡΠΆΠ΄Π΅Π½ΠΈΠ΅ ΠΏΠΎΠ΄ΠΏΠΈΡΠΊΠΈ ΠΈ Π½Π΅ ΠΏΡΠΈΡΡΡΡΡΠ²ΡΠ΅Ρ Π² Π²Π΅Π±Ρ
ΡΠΊΠ΅. ΠΡΡ
ΠΎΠ΄Ρ ΠΈΠ· Π½Π°Π»ΠΈΡΠΈΡ/ΠΎΡΡΡΡΡΡΠ²ΠΈΡ ΡΡΠΎΠΉ Π·Π°ΠΏΠΈΡΠΈ Π² POST-Π·Π°ΠΏΡΠΎΡΠ΅, Π΄Π°Π»ΡΠ½Π΅ΠΉΡΠ΅Π΅ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ ΠΏΠ΅ΡΠ΅Ρ
ΠΎΠ΄ΠΈΡ Π»ΠΈΠ±ΠΎ Π² ΡΡΠ½ΠΊΡΠΈΡ SubscriptionConfirmation
, Π»ΠΈΠ±ΠΎ Π² ΡΡΠ½ΠΊΡΠΈΡ GotRecords
.
Π€ΡΠ½ΠΊΡΠΈΡ SubscriptionConfirmation Π΄Π΅ΡΠ°Π»ΡΠ½ΠΎ ΡΠ°ΡΡΠΌΠ°ΡΡΠΈΠ²Π°ΡΡ Π½Π΅ Π±ΡΠ΄Π΅ΠΌ, ΠΎΠ½Π° ΡΠ΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π° ΠΏΠΎ ΠΏΡΠΈΠ½ΡΠΈΠΏΠ°ΠΌ, ΠΈΠ·Π»ΠΎΠΆΠ΅Π½Π½ΡΠΌ Π²
Π€ΡΠ½ΠΊΡΠΈΡ GotRecords ΡΠ°Π·Π±ΠΈΡΠ°Π΅Ρ ΠΏΡΠΈΡ ΠΎΠ΄ΡΡΠΈΠΉ Π·Π°ΠΏΡΠΎΡ ΠΈ Π΄Π»Ρ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΠΎΠ±ΡΠ΅ΠΊΡΠ° Record Π²ΡΠ·ΡΠ²Π°Π΅Ρ Π²Π½Π΅ΡΠ½ΠΈΠΉ ΡΠΊΡΠΈΠΏΡ (ΠΈΠΌΡ ΠΊΠΎΡΠΎΡΠΎΠ³ΠΎ Π±ΡΠ»ΠΎ ΠΏΠ΅ΡΠ΅Π΄Π°Π½ΠΎ Π² ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠ΅ -script) Ρ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠ°ΠΌΠΈ:
- ΠΈΠΌΡ Π±Π°ΠΊΠ΅ΡΠ°
- ΠΊΠ»ΡΡ ΠΎΠ±ΡΠ΅ΠΊΡΠ°
- Π΄Π΅ΠΉΡΡΠ²ΠΈΠ΅:
- copy β Π΅ΡΠ»ΠΈ Π² ΠΈΡΡ ΠΎΠ΄Π½ΠΎΠΌ Π·Π°ΠΏΡΠΎΡΠ΅ EventName = ObjectCreated | PutObject | PutObjectCopy
- delete β Π΅ΡΠ»ΠΈ Π² ΠΈΡΡ ΠΎΠ΄Π½ΠΎΠΌ Π·Π°ΠΏΡΠΎΡΠ΅ EventName = ObjectRemoved | DeleteObject
Π’Π°ΠΊΠΈΠΌ ΠΎΠ±ΡΠ°Π·ΠΎΠΌ, Π΅ΡΠ»ΠΈ ΠΏΡΠΈΠ»Π΅ΡΠ΅Π» Ρ
ΡΠΊ c Post-Π·Π°ΠΏΡΠΎΡΠΎΠΌ, ΠΊΠ°ΠΊ ΠΎΠΏΠΈΡΠ°Π½ΠΎ
script.sh bucketA some-file-to-bucket copy
Π‘Π»Π΅Π΄ΡΠ΅Ρ ΠΏΠΎΠ½ΠΈΠΌΠ°ΡΡ, ΡΡΠΎ Π΄Π°Π½Π½ΡΠΉ ΡΠ΅ΡΠ²Π΅Ρ ΠΏΡΠΈΠ΅ΠΌΠ° Π²Π΅Π±Ρ ΡΠΊΠΎΠ² β ΡΡΠΎ Π½Π΅ Π·Π°ΠΊΠΎΠ½ΡΠ΅Π½Π½ΠΎΠ΅ production-ΡΠ΅ΡΠ΅Π½ΠΈΠ΅, Π° ΡΠΏΡΠΎΡΠ΅Π½Π½ΡΠΉ ΠΏΡΠΈΠΌΠ΅Ρ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΠΉ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ.
ΠΡΠΈΠΌΠ΅Ρ ΡΠ°Π±ΠΎΡΡ
Π‘Π΄Π΅Π»Π°Π΅ΠΌ ΡΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·Π°ΡΠΈΡ ΡΠ°ΠΉΠ»ΠΎΠ² ΠΎΡΠ½ΠΎΠ²Π½ΠΎΠ³ΠΎ Π±Π°ΠΊΠ΅ΡΠ° Π² MCS Π² ΡΠ΅Π·Π΅ΡΠ²Π½ΡΠΉ Π±Π°ΠΊΠ΅Ρ Π² AWS. ΠΡΠ½ΠΎΠ²Π½ΠΎΠΉ Π±Π°ΠΊΠ΅Ρ Π½Π°Π·ΡΠ²Π°Π΅ΡΡΡ myfiles-ash, ΡΠ΅Π·Π΅ΡΠ²Π½ΡΠΉ β myfiles-backup (ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡ Π±Π°ΠΊΠ΅ΡΠ° Π² AWS Π²ΡΡ ΠΎΠ΄ΠΈΡ Π·Π° ΠΏΡΠ΅Π΄Π΅Π»Ρ Π΄Π°Π½Π½ΠΎΠΉ ΡΡΠ°ΡΡΠΈ). Π‘ΠΎΠΎΡΠ²Π΅ΡΡΡΠ²Π΅Π½Π½ΠΎ, ΠΊΠΎΠ³Π΄Π° ΡΠ°ΠΉΠ» ΠΊΠ»Π°Π΄Π΅ΡΡΡ Π² ΠΎΡΠ½ΠΎΠ²Π½ΠΎΠΉ Π±Π°ΠΊΠ΅Ρ, Π΅Π³ΠΎ ΠΊΠΎΠΏΠΈΡ Π΄ΠΎΠ»ΠΆΠ½Π° ΠΏΠΎΡΠ²ΠΈΡΡΡΡ Π² ΡΠ΅Π·Π΅ΡΠ²Π½ΠΎΠΌ, ΠΊΠΎΠ³Π΄Π° ΡΠ΄Π°Π»ΡΠ΅ΡΡΡ ΠΈΠ· ΠΎΡΠ½ΠΎΠ²Π½ΠΎΠ³ΠΎ β ΡΠ΄Π°Π»ΡΡΡΡΡ Π² ΡΠ΅Π·Π΅ΡΠ²Π½ΠΎΠΌ.
Π Π°Π±ΠΎΡΠ°ΡΡ Ρ Π±Π°ΠΊΠ΅ΡΠ°ΠΌΠΈ Π±ΡΠ΄Π΅ΠΌ ΡΡΠΈΠ»ΠΈΡΠΎΠΉ awscli, Ρ ΠΊΠΎΡΠΎΡΠΎΠΉ ΡΠΎΠ²ΠΌΠ΅ΡΡΠΈΠΌΠΎ ΠΊΠ°ΠΊ ΠΎΠ±Π»Π°ΡΠ½ΠΎΠ΅ Ρ ΡΠ°Π½ΠΈΠ»ΠΈΡΠ΅ MCS, ΡΠ°ΠΊ ΠΈ ΠΎΠ±Π»Π°ΡΠ½ΠΎΠ΅ Ρ ΡΠ°Π½ΠΈΠ»ΠΈΡΠ΅ AWS.
ubuntu@ubuntu-basic-1-2-10gb:~$ sudo apt-get install awscli
Reading package lists... Done
Building dependency tree
Reading state information... Done
After this operation, 34.4 MB of additional disk space will be used.
Unpacking awscli (1.14.44-1ubuntu1) ...
Setting up awscli (1.14.44-1ubuntu1) ...
Π‘ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠΈΡΡΠ΅ΠΌ Π΄ΠΎΡΡΡΠΏ ΠΊ API S3 MCS:
ubuntu@ubuntu-basic-1-2-10gb:~$ aws configure --profile mcs
AWS Access Key ID [None]: hdywEPtuuJTExxxxxxxxxxxxxx
AWS Secret Access Key [None]: hDz3SgxKwXoxxxxxxxxxxxxxxxxxx
Default region name [None]:
Default output format [None]:
Π‘ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠΈΡΡΠ΅ΠΌ Π΄ΠΎΡΡΡΠΏ ΠΊ API S3 AWS:
ubuntu@ubuntu-basic-1-2-10gb:~$ aws configure --profile aws
AWS Access Key ID [None]: AKIAJXXXXXXXXXXXX
AWS Secret Access Key [None]: dfuerphOLQwu0CreP5Z8l5fuXXXXXXXXXXXXXXXX
Default region name [None]:
Default output format [None]:
ΠΡΠΎΠ²Π΅ΡΠΈΠΌ Π΄ΠΎΡΡΡΠΏΡ:
Π AWS:
ubuntu@ubuntu-basic-1-2-10gb:~$ aws s3 ls --profile aws
2020-07-06 08:44:11 myfiles-backup
ΠΠ»Ρ MCS, ΠΏΡΠΈ ΡΠ°Π±ΠΎΡΠ΅ ΠΊΠΎΠΌΠ°Π½Π΄Ρ Π½Π°Π΄ΠΎ Π΄ΠΎΠ±Π°Π²Π»ΡΡΡ —endpoint-url:
ubuntu@ubuntu-basic-1-2-10gb:~$ aws s3 ls --profile mcs --endpoint-url
https://hb.bizmrg.com
2020-02-04 06:38:05 databasebackups-0cdaaa6402d4424e9676c75a720afa85
2020-05-27 10:08:33 myfiles-ash
ΠΠΎΡΡΡΠΏ ΠΏΠΎΠ»ΡΡΠ΅Π½.
Π’Π΅ΠΏΠ΅ΡΡ Π½Π°ΠΏΠΈΡΠ΅ΠΌ ΡΠΊΡΠΈΠΏΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ ΠΏΡΠΈΡ ΠΎΠ΄ΡΡΠ΅Π³ΠΎ Ρ ΡΠΊΠ°, Π½Π°Π·ΠΎΠ²Π΅ΠΌ Π΅Π³ΠΎ s3_backup_mcs_aws.sh
#!/bin/bash
# Require aws cli
# if file added β copy it to backup bucket
# if file removed β remove it from backup bucket
# Variables
ENDPOINT_MCS="https://hb.bizmrg.com"
AWSCLI_MCS=`which aws`" --endpoint-url ${ENDPOINT_MCS} --profile mcs s3"
AWSCLI_AWS=`which aws`" --profile aws s3"
BACKUP_BUCKET="myfiles-backup"
SOURCE_BUCKET=""
SOURCE_FILE=""
ACTION=""
SOURCE="s3://${SOURCE_BUCKET}/${SOURCE_FILE}"
TARGET="s3://${BACKUP_BUCKET}/${SOURCE_FILE}"
TEMP="/tmp/${SOURCE_BUCKET}/${SOURCE_FILE}"
case ${ACTION} in
"copy")
${AWSCLI_MCS} cp "${SOURCE}" "${TEMP}"
${AWSCLI_AWS} cp "${TEMP}" "${TARGET}"
rm ${TEMP}
;;
"delete")
${AWSCLI_AWS} rm ${TARGET}
;;
*)
echo "Usage: #!/bin/bash
# Require aws cli
# if file added β copy it to backup bucket
# if file removed β remove it from backup bucket
# Variables
ENDPOINT_MCS="https://hb.bizmrg.com"
AWSCLI_MCS=`which aws`" --endpoint-url ${ENDPOINT_MCS} --profile mcs s3"
AWSCLI_AWS=`which aws`" --profile aws s3"
BACKUP_BUCKET="myfiles-backup"
SOURCE_BUCKET="${1}"
SOURCE_FILE="${2}"
ACTION="${3}"
SOURCE="s3://${SOURCE_BUCKET}/${SOURCE_FILE}"
TARGET="s3://${BACKUP_BUCKET}/${SOURCE_FILE}"
TEMP="/tmp/${SOURCE_BUCKET}/${SOURCE_FILE}"
case ${ACTION} in
"copy")
${AWSCLI_MCS} cp "${SOURCE}" "${TEMP}"
${AWSCLI_AWS} cp "${TEMP}" "${TARGET}"
rm ${TEMP}
;;
"delete")
${AWSCLI_AWS} rm ${TARGET}
;;
*)
echo "Usage: ${0} sourcebucket sourcefile copy/delete"
exit 1
;;
esac
sourcebucket sourcefile copy/delete"
exit 1
;;
esac
ΠΠ°ΠΏΡΡΠΊΠ°Π΅ΠΌ ΡΠ΅ΡΠ²Π΅Ρ:
ubuntu@ubuntu-basic-1-2-10gb:~/s3-webhook$ sudo ./s3-webhook -port 80 -
script scripts/s3_backup_mcs_aws.sh
ΠΡΠΎΠ²Π΅ΡΡΠ΅ΠΌ, ΠΊΠ°ΠΊ ΡΡΠΎ ΡΡΠ°Π±ΠΎΡΠ°Π΅Ρ. Π§Π΅ΡΠ΅Π·
2020/07/06 09:43:08 [POST] incoming HTTP request from
95.163.216.92:56612
download: s3://myfiles-ash/test.txt to ../../../tmp/myfiles-ash/test.txt
upload: ../../../tmp/myfiles-ash/test.txt to
s3://myfiles-backup/test.txt
ΠΡΠΎΠ²Π΅ΡΠΈΠΌ ΡΠΎΠ΄Π΅ΡΠΆΠΈΠΌΠΎΠ΅ Π±Π°ΠΊΠ΅ΡΠ° myfiles-backup Π² AWS:
ubuntu@ubuntu-basic-1-2-10gb:~/s3-webhook$ aws s3 --profile aws ls
myfiles-backup
2020-07-06 09:43:10 1104 test.txt
Π’Π΅ΠΏΠ΅ΡΡ ΡΠ΅ΡΠ΅Π· Π²Π΅Π±-ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ ΡΠ΄Π°Π»ΠΈΠΌ ΡΠ°ΠΉΠ» ΠΈΠ· Π±Π°ΠΊΠ΅ΡΠ° myfiles-ash.
ΠΠΎΠ³ΠΈ ΡΠ΅ΡΠ²Π΅ΡΠ°:
2020/07/06 09:44:46 [POST] incoming HTTP request from
95.163.216.92:58224
delete: s3://myfiles-backup/test.txt
Π‘ΠΎΠ΄Π΅ΡΠΆΠΈΠΌΠΎΠ΅ Π±Π°ΠΊΠ΅ΡΠ°:
ubuntu@ubuntu-basic-1-2-10gb:~/s3-webhook$ aws s3 --profile aws ls
myfiles-backup
ubuntu@ubuntu-basic-1-2-10gb:~$
Π€Π°ΠΉΠ» ΡΠ΄Π°Π»Π΅Π½, Π·Π°Π΄Π°ΡΠ° ΡΠ΅ΡΠ΅Π½Π°.
ΠΠ°ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΠΈ ToDo
ΠΠ΅ΡΡ ΠΊΠΎΠ΄, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌΡΠΉ Π² ΡΡΠΎΠΉ ΡΡΠ°ΡΡΠ΅, Π»Π΅ΠΆΠΈΡ
ΠΠ°Π½Π½ΡΠΉ ΠΊΠΎΠ΄ β Π½Π΅ Π±ΠΎΠ»Π΅Π΅ ΡΠ΅ΠΌ ΠΏΡΠΈΠΌΠ΅Ρ ΡΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ S3-Π²Π΅Π±Ρ ΡΠΊΠΈ Π² ΡΠ²ΠΎΠ΅ΠΉ Π΄Π΅ΡΡΠ΅Π»ΡΠ½ΠΎΡΡΠΈ. ΠΠ°ΠΊ Ρ ΡΠΊΠ°Π·Π°Π» Π² Π½Π°ΡΠ°Π»Π΅, Π΅ΡΠ»ΠΈ ΠΏΠ»Π°Π½ΠΈΡΠΎΠ²Π°ΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ ΡΠ°ΠΊΠΎΠ³ΠΎ ΡΠ΅ΡΠ²Π΅ΡΠ° Π² ΠΏΡΠΎΠ΄ΡΠΊΡΠΈΠ²Π΅, Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ ΠΊΠ°ΠΊ ΠΌΠΈΠ½ΠΈΠΌΡΠΌ ΠΏΠ΅ΡΠ΅ΠΏΠΈΡΡΠ²Π°ΡΡ ΡΠ΅ΡΠ²Π΅Ρ ΠΏΠΎΠ΄ Π°ΡΠΈΠ½Ρ ΡΠΎΠ½Π½ΡΡ ΡΠ°Π±ΠΎΡΡ: ΠΏΡΠΈΡ ΠΎΠ΄ΡΡΠΈΠ΅ Π²Π΅Π±Ρ ΡΠΊΠΈ ΡΠ΅Π³ΠΈΡΡΡΠΈΡΠΎΠ²Π°ΡΡ Π² ΠΎΡΠ΅ΡΠ΅Π΄ΠΈ (RabbitMQ ΠΈΠ»ΠΈ NATS), Π° ΠΎΡΡΡΠ΄Π° ΠΈΡ ΡΠ°Π·Π±ΠΈΡΠ°ΡΡ ΠΈ ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°ΡΡ worker-ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡΠΌΠΈ. ΠΠ½Π°ΡΠ΅ ΠΏΡΠΈ ΠΌΠ°ΡΡΠΈΡΠΎΠ²Π°Π½Π½ΠΎΠΌ ΠΏΡΠΈΡ ΠΎΠ΄Π΅ Π²Π΅Π±Ρ ΡΠΊΠΎΠ² ΠΌΠΎΠΆΠ½ΠΎ ΡΡΠΎΠ»ΠΊΠ½ΡΡΡΡΡ Ρ Π½Π΅Ρ Π²Π°ΡΠΊΠΎΠΉ ΡΠ΅ΡΡΡΡΠΎΠ² ΡΠ΅ΡΠ²Π΅ΡΠ° Π΄Π»Ρ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ Π·Π°Π΄Π°Ρ. ΠΠ°Π»ΠΈΡΠΈΠ΅ ΠΆΠ΅ ΠΎΡΠ΅ΡΠ΅Π΄Π΅ΠΉ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ ΡΠ°Π·Π½ΠΎΡΠΈΡΡ ΡΠ΅ΡΠ²Π΅Ρ ΠΈ workers, Π° ΡΠ°ΠΊΠΆΠ΅ ΡΠ΅ΡΠ°ΡΡ Π²ΠΎΠΏΡΠΎΡΡ Ρ ΠΏΠΎΠ²ΡΠΎΡΠΎΠΌ Π·Π°Π΄Π°Ρ Π² ΡΠ»ΡΡΠ°Π΅ ΡΠ±ΠΎΠ΅Π². Π’Π°ΠΊ ΠΆΠ΅ ΠΆΠ΅Π»Π°ΡΠ΅Π»ΡΠ½ΠΎ ΠΌΠ΅Π½ΡΡΡ Π»ΠΎΠ³ΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ Π½Π° Π±ΠΎΠ»Π΅Π΅ ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΠΎΠ΅ ΠΈ Π±ΠΎΠ»Π΅Π΅ ΡΡΠ°Π½Π΄Π°ΡΡΠΈΠ·ΠΎΠ²Π°Π½Π½ΠΎΠ΅.
Π£ΡΠΏΠ΅Ρ ΠΎΠ²!
ΠΡΠ΅ ΠΏΠΎΡΠΈΡΠ°ΡΡ ΠΏΠΎ ΡΠ΅ΠΌΠ΅:
Π Π°Π±ΠΎΡΠ° Ρ ΠΎΠ±ΡΠ΅ΠΊΡΠ½ΡΠΌ S3-Ρ ΡΠ°Π½ΠΈΠ»ΠΈΡΠ΅ΠΌ Mail.ru Cloud Solutions ΠΊΠ°ΠΊ Ρ ΡΠ°ΠΉΠ»ΠΎΠ²ΠΎΠΉ ΡΠΈΡΡΠ΅ΠΌΠΎΠΉ. ΠΠ°ΠΊ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡΡ ΠΎΠ±ΡΠ΅ΠΊΡΠ½ΠΎΠ΅ Ρ ΡΠ°Π½ΠΈΠ»ΠΈΡΠ΅, ΡΡΠΎΠ±Ρ ΠΎΠ±ΡΠ³ΡΠ°ΡΡ ΠΊΠΎΠ½ΠΊΡΡΠ΅Π½ΡΠΎΠ².
ΠΡΡΠΎΡΠ½ΠΈΠΊ: habr.com