Repository: GoogleCloudPlatform/gce-rescue (language: python)

Issue:
Versioning
* Replace hardcoded version
* Implement global VERSION + bumpversion
* Add VERSION to userAgent


Discussion / hints:

Fix patch:
diff --git a/.bumpversion.cfg b/.bumpversion.cfg
new file mode 100644
index 0000000..8cb9f8d
--- /dev/null
+++ b/.bumpversion.cfg
@@ -0,0 +1,17 @@
+[bumpversion]
+current_version = 0.3-beta
+parse = (?P<major>\d+)\.(?P<minor>\d+)(-(?P<release>.*))?
+message = Bump version: {current_version} -> {new_version}
+serialize = 
+	{major}.{minor}-{release}
+	{major}.{minor}
+
+[bumpversion:part:release]
+optional_value = release
+values = 
+	beta
+	release
+
+[bumpversion:file:gce_rescue/config.py]
+search = VERSION = '{current_version}'
+replace = VERSION = '{new_version}'
diff --git a/.gitignore b/.gitignore
index f123127..1043ee9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,4 +22,4 @@ poetry.lock
 *.DS_Store
 .vscode/
 .idea
-debian.log
+*.log
diff --git a/Makefile b/Makefile
index 82c9943..1087a61 100644
--- a/Makefile
+++ b/Makefile
@@ -7,6 +7,9 @@ test:
 requirements: requirements.txt
 	python3 -m pip install -r requirements.txt
 
+bumpversion:
+	pipenv run bumpversion --commit minor
+
 build: setup.py
 	python3 ./setup.py bdist_wheel sdist
 
diff --git a/Pipfile b/Pipfile
index e03cf6c..464194f 100644
--- a/Pipfile
+++ b/Pipfile
@@ -8,6 +8,7 @@ absl-py = ">=1.2.0"
 google-api-python-client = "*"
 google-auth = "*"
 pylint = "*"
+bumpversion = "*"
 
 [dev-packages]
 bump2version = "*"
diff --git a/Pipfile.lock b/Pipfile.lock
index 088e4f5..7104f33 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
 {
     "_meta": {
         "hash": {
-            "sha256": "3d94110b5d49dc85032d0e3e885d82860298040c5abd33297c6f30ea93f2248e"
+            "sha256": "f8c14c79e90c97984625a7af2e56c3a0fca089c9e4bfed4e16835bbc9ba27f1d"
         },
         "pipfile-spec": 6,
         "requires": {
@@ -26,11 +26,27 @@
         },
         "astroid": {
             "hashes": [
-                "sha256:0e0e3709d64fbffd3037e4ff403580550f14471fd3eaae9fa11cc9a5c7901153",
-                "sha256:a3cf9f02c53dd259144a7e8f3ccd75d67c9a8c716ef183e0c1f291bc5d7bb3cf"
+                "sha256:a1b8543ef9d36ea777194bc9b17f5f8678d2c56ee6a45b2c2f17eec96f242347",
+                "sha256:c81e1c7fbac615037744d067a9bb5f9aeb655edf59b63ee8b59585475d6f80d8"
             ],
             "markers": "python_full_version >= '3.7.2'",
-            "version": "==2.14.2"
+            "version": "==2.15.4"
+        },
+        "bump2version": {
+            "hashes": [
+                "sha256:37f927ea17cde7ae2d7baf832f8e80ce3777624554a653006c9144f8017fe410",
+                "sha256:762cb2bfad61f4ec8e2bdf452c7c267416f8c70dd9ecb1653fd0bbb01fa936e6"
+            ],
+            "markers": "python_version >= '3.5'",
+            "version": "==1.0.1"
+        },
+        "bumpversion": {
+            "hashes": [
+                "sha256:4ba55e4080d373f80177b4dabef146c07ce73c7d1377aabf9d3c3ae1f94584a6",
+                "sha256:4eb3267a38194d09f048a2179980bb4803701969bff2c85fa8f6d1ce050be15e"
+            ],
+            "index": "pypi",
+            "version": "==0.6.0"
         },
         "cachetools": {
             "hashes": [
@@ -42,106 +58,93 @@
         },
         "certifi": {
             "hashes": [
-                "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3",
-                "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"
+                "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7",
+                "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"
             ],
             "index": "pypi",
             "markers": "python_version >= '3.6'",
-            "version": "==2022.12.7"
+            "version": "==2023.5.7"
         },
         "charset-normalizer": {
             "hashes": [
-                "sha256:00d3ffdaafe92a5dc603cb9bd5111aaa36dfa187c8285c543be562e61b755f6b",
-                "sha256:024e606be3ed92216e2b6952ed859d86b4cfa52cd5bc5f050e7dc28f9b43ec42",
-                "sha256:0298eafff88c99982a4cf66ba2efa1128e4ddaca0b05eec4c456bbc7db691d8d",
-                "sha256:02a51034802cbf38db3f89c66fb5d2ec57e6fe7ef2f4a44d070a593c3688667b",
-                "sha256:083c8d17153ecb403e5e1eb76a7ef4babfc2c48d58899c98fcaa04833e7a2f9a",
-                "sha256:0a11e971ed097d24c534c037d298ad32c6ce81a45736d31e0ff0ad37ab437d59",
-                "sha256:0bf2dae5291758b6f84cf923bfaa285632816007db0330002fa1de38bfcb7154",
-                "sha256:0c0a590235ccd933d9892c627dec5bc7511ce6ad6c1011fdf5b11363022746c1",
-                "sha256:0f438ae3532723fb6ead77e7c604be7c8374094ef4ee2c5e03a3a17f1fca256c",
-                "sha256:109487860ef6a328f3eec66f2bf78b0b72400280d8f8ea05f69c51644ba6521a",
-                "sha256:11b53acf2411c3b09e6af37e4b9005cba376c872503c8f28218c7243582df45d",
-                "sha256:12db3b2c533c23ab812c2b25934f60383361f8a376ae272665f8e48b88e8e1c6",
-                "sha256:14e76c0f23218b8f46c4d87018ca2e441535aed3632ca134b10239dfb6dadd6b",
-                "sha256:16a8663d6e281208d78806dbe14ee9903715361cf81f6d4309944e4d1e59ac5b",
-                "sha256:292d5e8ba896bbfd6334b096e34bffb56161c81408d6d036a7dfa6929cff8783",
-                "sha256:2c03cc56021a4bd59be889c2b9257dae13bf55041a3372d3295416f86b295fb5",
-                "sha256:2e396d70bc4ef5325b72b593a72c8979999aa52fb8bcf03f701c1b03e1166918",
-                "sha256:2edb64ee7bf1ed524a1da60cdcd2e1f6e2b4f66ef7c077680739f1641f62f555",
-                "sha256:31a9ddf4718d10ae04d9b18801bd776693487cbb57d74cc3458a7673f6f34639",
-                "sha256:356541bf4381fa35856dafa6a965916e54bed415ad8a24ee6de6e37deccf2786",
-                "sha256:358a7c4cb8ba9b46c453b1dd8d9e431452d5249072e4f56cfda3149f6ab1405e",
-                "sha256:37f8febc8ec50c14f3ec9637505f28e58d4f66752207ea177c1d67df25da5aed",
-                "sha256:39049da0ffb96c8cbb65cbf5c5f3ca3168990adf3551bd1dee10c48fce8ae820",
-                "sha256:39cf9ed17fe3b1bc81f33c9ceb6ce67683ee7526e65fde1447c772afc54a1bb8",
-                "sha256:3ae1de54a77dc0d6d5fcf623290af4266412a7c4be0b1ff7444394f03f5c54e3",
-                "sha256:3b590df687e3c5ee0deef9fc8c547d81986d9a1b56073d82de008744452d6541",
-                "sha256:3e45867f1f2ab0711d60c6c71746ac53537f1684baa699f4f668d4c6f6ce8e14",
-                "sha256:3fc1c4a2ffd64890aebdb3f97e1278b0cc72579a08ca4de8cd2c04799a3a22be",
-                "sha256:4457ea6774b5611f4bed5eaa5df55f70abde42364d498c5134b7ef4c6958e20e",
-                "sha256:44ba614de5361b3e5278e1241fda3dc1838deed864b50a10d7ce92983797fa76",
-                "sha256:4a8fcf28c05c1f6d7e177a9a46a1c52798bfe2ad80681d275b10dcf317deaf0b",
-                "sha256:4b0d02d7102dd0f997580b51edc4cebcf2ab6397a7edf89f1c73b586c614272c",
-                "sha256:502218f52498a36d6bf5ea77081844017bf7982cdbe521ad85e64cabee1b608b",
-                "sha256:503e65837c71b875ecdd733877d852adbc465bd82c768a067badd953bf1bc5a3",
-                "sha256:5995f0164fa7df59db4746112fec3f49c461dd6b31b841873443bdb077c13cfc",
-                "sha256:59e5686dd847347e55dffcc191a96622f016bc0ad89105e24c14e0d6305acbc6",
-                "sha256:601f36512f9e28f029d9481bdaf8e89e5148ac5d89cffd3b05cd533eeb423b59",
-                "sha256:608862a7bf6957f2333fc54ab4399e405baad0163dc9f8d99cb236816db169d4",
-                "sha256:62595ab75873d50d57323a91dd03e6966eb79c41fa834b7a1661ed043b2d404d",
-                "sha256:70990b9c51340e4044cfc394a81f614f3f90d41397104d226f21e66de668730d",
-                "sha256:71140351489970dfe5e60fc621ada3e0f41104a5eddaca47a7acb3c1b851d6d3",
-                "sha256:72966d1b297c741541ca8cf1223ff262a6febe52481af742036a0b296e35fa5a",
-                "sha256:74292fc76c905c0ef095fe11e188a32ebd03bc38f3f3e9bcb85e4e6db177b7ea",
-                "sha256:761e8904c07ad053d285670f36dd94e1b6ab7f16ce62b9805c475b7aa1cffde6",
-                "sha256:772b87914ff1152b92a197ef4ea40efe27a378606c39446ded52c8f80f79702e",
-                "sha256:79909e27e8e4fcc9db4addea88aa63f6423ebb171db091fb4373e3312cb6d603",
-                "sha256:7e189e2e1d3ed2f4aebabd2d5b0f931e883676e51c7624826e0a4e5fe8a0bf24",
-                "sha256:7eb33a30d75562222b64f569c642ff3dc6689e09adda43a082208397f016c39a",
-                "sha256:81d6741ab457d14fdedc215516665050f3822d3e56508921cc7239f8c8e66a58",
-                "sha256:8499ca8f4502af841f68135133d8258f7b32a53a1d594aa98cc52013fff55678",
-                "sha256:84c3990934bae40ea69a82034912ffe5a62c60bbf6ec5bc9691419641d7d5c9a",
-                "sha256:87701167f2a5c930b403e9756fab1d31d4d4da52856143b609e30a1ce7160f3c",
-                "sha256:88600c72ef7587fe1708fd242b385b6ed4b8904976d5da0893e31df8b3480cb6",
-                "sha256:8ac7b6a045b814cf0c47f3623d21ebd88b3e8cf216a14790b455ea7ff0135d18",
-                "sha256:8b8af03d2e37866d023ad0ddea594edefc31e827fee64f8de5611a1dbc373174",
-                "sha256:8c7fe7afa480e3e82eed58e0ca89f751cd14d767638e2550c77a92a9e749c317",
-                "sha256:8eade758719add78ec36dc13201483f8e9b5d940329285edcd5f70c0a9edbd7f",
-                "sha256:911d8a40b2bef5b8bbae2e36a0b103f142ac53557ab421dc16ac4aafee6f53dc",
-                "sha256:93ad6d87ac18e2a90b0fe89df7c65263b9a99a0eb98f0a3d2e079f12a0735837",
-                "sha256:95dea361dd73757c6f1c0a1480ac499952c16ac83f7f5f4f84f0658a01b8ef41",
-                "sha256:9ab77acb98eba3fd2a85cd160851816bfce6871d944d885febf012713f06659c",
-                "sha256:9cb3032517f1627cc012dbc80a8ec976ae76d93ea2b5feaa9d2a5b8882597579",
-                "sha256:9cf4e8ad252f7c38dd1f676b46514f92dc0ebeb0db5552f5f403509705e24753",
-                "sha256:9d9153257a3f70d5f69edf2325357251ed20f772b12e593f3b3377b5f78e7ef8",
-                "sha256:a152f5f33d64a6be73f1d30c9cc82dfc73cec6477ec268e7c6e4c7d23c2d2291",
-                "sha256:a16418ecf1329f71df119e8a65f3aa68004a3f9383821edcb20f0702934d8087",
-                "sha256:a60332922359f920193b1d4826953c507a877b523b2395ad7bc716ddd386d866",
-                "sha256:a8d0fc946c784ff7f7c3742310cc8a57c5c6dc31631269876a88b809dbeff3d3",
-                "sha256:ab5de034a886f616a5668aa5d098af2b5385ed70142090e2a31bcbd0af0fdb3d",
-                "sha256:c22d3fe05ce11d3671297dc8973267daa0f938b93ec716e12e0f6dee81591dc1",
-                "sha256:c2ac1b08635a8cd4e0cbeaf6f5e922085908d48eb05d44c5ae9eabab148512ca",
-                "sha256:c512accbd6ff0270939b9ac214b84fb5ada5f0409c44298361b2f5e13f9aed9e",
-                "sha256:c75ffc45f25324e68ab238cb4b5c0a38cd1c3d7f1fb1f72b5541de469e2247db",
-                "sha256:c95a03c79bbe30eec3ec2b7f076074f4281526724c8685a42872974ef4d36b72",
-                "sha256:cadaeaba78750d58d3cc6ac4d1fd867da6fc73c88156b7a3212a3cd4819d679d",
-                "sha256:cd6056167405314a4dc3c173943f11249fa0f1b204f8b51ed4bde1a9cd1834dc",
-                "sha256:db72b07027db150f468fbada4d85b3b2729a3db39178abf5c543b784c1254539",
-                "sha256:df2c707231459e8a4028eabcd3cfc827befd635b3ef72eada84ab13b52e1574d",
-                "sha256:e62164b50f84e20601c1ff8eb55620d2ad25fb81b59e3cd776a1902527a788af",
-                "sha256:e696f0dd336161fca9adbb846875d40752e6eba585843c768935ba5c9960722b",
-                "sha256:eaa379fcd227ca235d04152ca6704c7cb55564116f8bc52545ff357628e10602",
-                "sha256:ebea339af930f8ca5d7a699b921106c6e29c617fe9606fa7baa043c1cdae326f",
-                "sha256:f4c39b0e3eac288fedc2b43055cfc2ca7a60362d0e5e87a637beac5d801ef478",
-                "sha256:f5057856d21e7586765171eac8b9fc3f7d44ef39425f85dbcccb13b3ebea806c",
-                "sha256:f6f45710b4459401609ebebdbcfb34515da4fc2aa886f95107f556ac69a9147e",
-                "sha256:f97e83fa6c25693c7a35de154681fcc257c1c41b38beb0304b9c4d2d9e164479",
-                "sha256:f9d0c5c045a3ca9bedfc35dca8526798eb91a07aa7a2c0fee134c6c6f321cbd7",
-                "sha256:ff6f3db31555657f3163b15a6b7c6938d08df7adbfc9dd13d9d19edad678f1e8"
-            ],
-            "markers": "python_version >= '3.6'",
-            "version": "==3.0.1"
+                "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6",
+                "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1",
+                "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e",
+                "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373",
+                "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62",
+                "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230",
+                "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be",
+                "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c",
+                "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0",
+                "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448",
+                "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f",
+                "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649",
+                "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d",
+                "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0",
+                "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706",
+                "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a",
+                "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59",
+                "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23",
+                "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5",
+                "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb",
+                "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e",
+                "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e",
+                "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c",
+                "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28",
+                "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d",
+                "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41",
+                "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974",
+                "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce",
+                "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f",
+                "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1",
+                "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d",
+                "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8",
+                "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017",
+                "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31",
+                "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7",
+                "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8",
+                "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e",
+                "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14",
+                "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd",
+                "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d",
+                "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795",
+                "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b",
+                "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b",
+                "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b",
+                "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203",
+                "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f",
+                "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19",
+                "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1",
+                "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a",
+                "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac",
+                "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9",
+                "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0",
+                "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137",
+                "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f",
+                "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6",
+                "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5",
+                "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909",
+                "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f",
+                "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0",
+                "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324",
+                "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755",
+                "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb",
+                "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854",
+                "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c",
+                "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60",
+                "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84",
+                "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0",
+                "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b",
+                "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1",
+                "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531",
+                "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1",
+                "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11",
+                "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326",
+                "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df",
+                "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"
+            ],
+            "markers": "python_full_version >= '3.7.0'",
+            "version": "==3.1.0"
         },
         "dill": {
             "hashes": [
@@ -161,19 +164,19 @@
         },
         "google-api-python-client": {
             "hashes": [
-                "sha256:42a44e9adfca6bb27540ce52348aa1d3b81e214bcc53d454a76ebfbe8eee1483",
-                "sha256:f18e9dbb365f0485194a8daf5d60da2cff6a80ce2c9a694efc2b279922cb3dd0"
+                "sha256:0f320190ab9d5bd2fdb0cb894e8e53bb5e17d4888ee8dc4d26ba65ce378409e2",
+                "sha256:3ca4e93821f4e9ac29b91ab0d9df168b42c8ad0fb8bff65b8c2ccb2d462b0464"
             ],
             "index": "pypi",
-            "version": "==2.77.0"
+            "version": "==2.86.0"
         },
         "google-auth": {
             "hashes": [
-                "sha256:5045648c821fb72384cdc0e82cc326df195f113a33049d9b62b74589243d2acc",
-                "sha256:ed7057a101af1146f0554a769930ac9de506aeca4fd5af6543ebe791851a9fbd"
+                "sha256:ce311e2bc58b130fddf316df57c9b3943c2a7b4f6ec31de9663a9333e4064efc",
+                "sha256:f586b274d3eb7bd932ea424b1c702a30e0393a2e2bc4ca3eae8263ffd8be229f"
             ],
             "index": "pypi",
-            "version": "==2.16.0"
+            "version": "==2.17.3"
         },
         "google-auth-httplib2": {
             "hashes": [
@@ -184,19 +187,19 @@
         },
         "googleapis-common-protos": {
             "hashes": [
-                "sha256:c727251ec025947d545184ba17e3578840fc3a24a0516a020479edab660457df",
-                "sha256:ca3befcd4580dab6ad49356b46bf165bb68ff4b32389f028f1abd7c10ab9519a"
+                "sha256:4168fcb568a826a52f23510412da405abd93f4d23ba544bb68d943b14ba3cb44",
+                "sha256:b287dc48449d1d41af0c69f4ea26242b5ae4c3d7249a38b0984c86a4caffff1f"
             ],
             "markers": "python_version >= '3.7'",
-            "version": "==1.58.0"
+            "version": "==1.59.0"
         },
         "httplib2": {
             "hashes": [
-                "sha256:987c8bb3eb82d3fa60c68699510a692aa2ad9c4bd4f123e51dfb1488c14cdd01",
-                "sha256:fc144f091c7286b82bec71bdbd9b27323ba709cc612568d3000893bfd9cb4b34"
+                "sha256:14ae0a53c1ba8f3d37e9e27cf37eabb0fb9980f435ba405d546948b009dd64dc",
+                "sha256:d7a10bc5ef5ab08322488bde8c726eeee5c8618723fdb399597ec58f3d82df81"
             ],
             "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
-            "version": "==0.21.0"
+            "version": "==0.22.0"
         },
         "idna": {
             "hashes": [
@@ -266,75 +269,54 @@
         },
         "platformdirs": {
             "hashes": [
-                "sha256:8a1228abb1ef82d788f74139988b137e78692984ec7b08eaa6c65f1723af28f9",
-                "sha256:b1d5eb14f221506f50d6604a561f4c5786d9e80355219694a1b244bcd96f4567"
+                "sha256:47692bc24c1958e8b0f13dd727307cff1db103fca36399f457da8e05f222fdc4",
+                "sha256:7954a68d0ba23558d753f73437c55f89027cf8f5108c19844d4b82e5af396335"
             ],
             "markers": "python_version >= '3.7'",
-            "version": "==3.0.0"
+            "version": "==3.5.0"
         },
         "protobuf": {
             "hashes": [
-                "sha256:1f22ac0ca65bb70a876060d96d914dae09ac98d114294f77584b0d2644fa9c30",
-                "sha256:237216c3326d46808a9f7c26fd1bd4b20015fb6867dc5d263a493ef9a539293b",
-                "sha256:27f4d15021da6d2b706ddc3860fac0a5ddaba34ab679dc182b60a8bb4e1121cc",
-                "sha256:299ea899484ee6f44604deb71f424234f654606b983cb496ea2a53e3c63ab791",
-                "sha256:3d164928ff0727d97022957c2b849250ca0e64777ee31efd7d6de2e07c494717",
-                "sha256:6ab80df09e3208f742c98443b6166bcb70d65f52cfeb67357d52032ea1ae9bec",
-                "sha256:78a28c9fa223998472886c77042e9b9afb6fe4242bd2a2a5aced88e3f4422aa7",
-                "sha256:7cd532c4566d0e6feafecc1059d04c7915aec8e182d1cf7adee8b24ef1e2e6ab",
-                "sha256:89f9149e4a0169cddfc44c74f230d7743002e3aa0b9472d8c28f0388102fc4c2",
-                "sha256:a53fd3f03e578553623272dc46ac2f189de23862e68565e83dde203d41b76fc5",
-                "sha256:b135410244ebe777db80298297a97fbb4c862c881b4403b71bac9d4107d61fd1",
-                "sha256:b98d0148f84e3a3c569e19f52103ca1feacdac0d2df8d6533cf983d1fda28462",
-                "sha256:d1736130bce8cf131ac7957fa26880ca19227d4ad68b4888b3be0dea1f95df97",
-                "sha256:f45460f9ee70a0ec1b6694c6e4e348ad2019275680bd68a1d9314b8c7e01e574"
+                "sha256:03eee35b60317112a72d19c54d0bff7bc58ff12fea4cd7b018232bd99758ffdf",
+                "sha256:2b94bd6df92d71bd1234a2ffe7ce96ddf6d10cf637a18d6b55ad0a89fbb7fc21",
+                "sha256:36f5370a930cb77c8ad2f4135590c672d0d2c72d4a707c7d0058dce4b4b4a598",
+                "sha256:5f1eba1da2a2f3f7df469fccddef3cc060b8a16cfe3cc65961ad36b4dbcf59c5",
+                "sha256:6c16657d6717a0c62d5d740cb354fbad1b0d8cb811669e06fc1caa0ff4799ddd",
+                "sha256:6fe180b56e1169d72ecc4acbd39186339aed20af5384531b8e8979b02bbee159",
+                "sha256:7cb5b9a05ce52c6a782bb97de52679bd3438ff2b7460eff5da348db65650f227",
+                "sha256:9744e934ea5855d12191040ea198eaf704ac78665d365a89d9572e3b627c2688",
+                "sha256:9f5a0fbfcdcc364f3986f9ed9f8bb1328fb84114fd790423ff3d7fdb0f85c2d1",
+                "sha256:baca40d067dddd62141a129f244703160d278648b569e90bb0e3753067644711",
+                "sha256:d5a35ff54e3f62e8fc7be02bb0d2fbc212bba1a5a9cc2748090690093996f07b",
+                "sha256:e62fb869762b4ba18666370e2f8a18f17f8ab92dd4467295c6d38be6f8fef60b",
+                "sha256:ebde3a023b8e11bfa6c890ef34cd6a8b47d586f26135e86c21344fe433daf2e2"
             ],
             "markers": "python_version >= '3.7'",
-            "version": "==4.21.12"
+            "version": "==4.23.0"
         },
         "pyasn1": {
             "hashes": [
-                "sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359",
-                "sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576",
-                "sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf",
-                "sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7",
-                "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d",
-                "sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00",
-                "sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8",
-                "sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86",
-                "sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12",
-                "sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776",
-                "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba",
-                "sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2",
-                "sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3"
-            ],
-            "version": "==0.4.8"
+                "sha256:87a2121042a1ac9358cabcaf1d07680ff97ee6404333bacca15f76aa8ad01a57",
+                "sha256:97b7290ca68e62a832558ec3976f15cbf911bf5d7c7039d8b861c2a0ece69fde"
+            ],
+            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'",
+            "version": "==0.5.0"
         },
         "pyasn1-modules": {
             "hashes": [
-                "sha256:0845a5582f6a02bb3e1bde9ecfc4bfcae6ec3210dd270522fee602365430c3f8",
-                "sha256:0fe1b68d1e486a1ed5473f1302bd991c1611d319bba158e98b106ff86e1d7199",
-                "sha256:15b7c67fabc7fc240d87fb9aabf999cf82311a6d6fb2c70d00d3d0604878c811",
-                "sha256:426edb7a5e8879f1ec54a1864f16b882c2837bfd06eee62f2c982315ee2473ed",
-                "sha256:65cebbaffc913f4fe9e4808735c95ea22d7a7775646ab690518c056784bc21b4",
-                "sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e",
-                "sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74",
-                "sha256:a99324196732f53093a84c4369c996713eb8c89d360a496b599fb1a9c47fc3eb",
-                "sha256:b80486a6c77252ea3a3e9b1e360bc9cf28eaac41263d173c032581ad2f20fe45",
-                "sha256:c29a5e5cc7a3f05926aff34e097e84f8589cd790ce0ed41b67aed6857b26aafd",
-                "sha256:cbac4bc38d117f2a49aeedec4407d23e8866ea4ac27ff2cf7fb3e5b570df19e0",
-                "sha256:f39edd8c4ecaa4556e989147ebf219227e2cd2e8a43c7e7fcb1f1c18c5fd6a3d",
-                "sha256:fe0644d9ab041506b62782e92b06b8c68cca799e1a9636ec398675459e031405"
-            ],
-            "version": "==0.2.8"
+                "sha256:5bd01446b736eb9d31512a30d46c1ac3395d676c6f3cafa4c03eb54b9925631c",
+                "sha256:d3ccd6ed470d9ffbc716be08bd90efbd44d0734bc9303818f7336070984a162d"
+            ],
+            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'",
+            "version": "==0.3.0"
         },
         "pylint": {
             "hashes": [
-                "sha256:bad9d7c36037f6043a1e848a43004dfd5ea5ceb05815d713ba56ca4503a9fe37",
-                "sha256:ffe7fa536bb38ba35006a7c8a6d2efbfdd3d95bbf21199cad31f76b1c50aaf30"
+                "sha256:5dcf1d9e19f41f38e4e85d10f511e5b9c35e1aa74251bf95cdd8cb23584e2db1",
+                "sha256:7a1145fb08c251bdb5cca11739722ce64a63db479283d10ce718b2460e54123c"
             ],
             "index": "pypi",
-            "version": "==2.16.1"
+            "version": "==2.17.4"
         },
         "pyparsing": {
             "hashes": [
@@ -346,11 +328,11 @@
         },
         "requests": {
             "hashes": [
-                "sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa",
-                "sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf"
+                "sha256:10e94cc4f3121ee6da529d358cdaeaff2f1c409cd377dbc72b825852f2f7e294",
+                "sha256:239d7d4458afcb28a692cdd298d87542235f4ca8d36d03a15bfc128a6559a2f4"
             ],
-            "markers": "python_version >= '3.7' and python_version < '4'",
-            "version": "==2.28.2"
+            "markers": "python_version >= '3.7'",
+            "version": "==2.30.0"
         },
         "rsa": {
             "hashes": [
@@ -378,19 +360,19 @@
         },
         "tomlkit": {
             "hashes": [
-                "sha256:07de26b0d8cfc18f871aec595fda24d95b08fef89d147caa861939f37230bf4b",
-                "sha256:71b952e5721688937fb02cf9d354dbcf0785066149d2855e44531ebdd2b65d73"
+                "sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171",
+                "sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3"
             ],
-            "markers": "python_version >= '3.6'",
-            "version": "==0.11.6"
+            "markers": "python_version >= '3.7'",
+            "version": "==0.11.8"
         },
         "typing-extensions": {
             "hashes": [
-                "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa",
-                "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"
+                "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb",
+                "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"
             ],
             "markers": "python_version < '3.10'",
-            "version": "==4.4.0"
+            "version": "==4.5.0"
         },
         "uritemplate": {
             "hashes": [
@@ -402,81 +384,92 @@
         },
         "urllib3": {
             "hashes": [
-                "sha256:076907bf8fd355cde77728471316625a4d2f7e713c125f51953bb5b3eecf4f72",
-                "sha256:75edcdc2f7d85b137124a6c3c9fc3933cdeaa12ecb9a6a959f22797a0feca7e1"
+                "sha256:61717a1095d7e155cdb737ac7bb2f4324a858a1e2e6466f6d03ff630ca68d3cc",
+                "sha256:d055c2f9d38dc53c808f6fdc8eab7360b6fdbbde02340ed25cfbcd817c62469e"
             ],
-            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'",
-            "version": "==1.26.14"
+            "markers": "python_version >= '3.7'",
+            "version": "==2.0.2"
         },
         "wrapt": {
             "hashes": [
-                "sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3",
-                "sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b",
-                "sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4",
-                "sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2",
-                "sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656",
-                "sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3",
-                "sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff",
-                "sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310",
-                "sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a",
-                "sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57",
-                "sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069",
-                "sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383",
-                "sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe",
-                "sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87",
-                "sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d",
-                "sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b",
-                "sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907",
-                "sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f",
-                "sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0",
-                "sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28",
-                "sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1",
-                "sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853",
-                "sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc",
-                "sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3",
-                "sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3",
-                "sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164",
-                "sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1",
-                "sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c",
-                "sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1",
-                "sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7",
-                "sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1",
-                "sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320",
-                "sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed",
-                "sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1",
-                "sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248",
-                "sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c",
-                "sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456",
-                "sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77",
-                "sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef",
-                "sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1",
-                "sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7",
-                "sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86",
-                "sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4",
-                "sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d",
-                "sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d",
-                "sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8",
-                "sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5",
-                "sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471",
-                "sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00",
-                "sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68",
-                "sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3",
-                "sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d",
-                "sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735",
-                "sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d",
-                "sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569",
-                "sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7",
-                "sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59",
-                "sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5",
-                "sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb",
-                "sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b",
-                "sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f",
-                "sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462",
-                "sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015",
-                "sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af"
+                "sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0",
+                "sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420",
+                "sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a",
+                "sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c",
+                "sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079",
+                "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923",
+                "sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f",
+                "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1",
+                "sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8",
+                "sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86",
+                "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0",
+                "sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364",
+                "sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e",
+                "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c",
+                "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e",
+                "sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c",
+                "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727",
+                "sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff",
+                "sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e",
+                "sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29",
+                "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7",
+                "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72",
+                "sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475",
+                "sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a",
+                "sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317",
+                "sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2",
+                "sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd",
+                "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640",
+                "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98",
+                "sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248",
+                "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e",
+                "sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d",
+                "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec",
+                "sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1",
+                "sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e",
+                "sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9",
+                "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92",
+                "sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb",
+                "sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094",
+                "sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46",
+                "sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29",
+                "sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd",
+                "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705",
+                "sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8",
+                "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975",
+                "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb",
+                "sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e",
+                "sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b",
+                "sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418",
+                "sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019",
+                "sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1",
+                "sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba",
+                "sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6",
+                "sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2",
+                "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3",
+                "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7",
+                "sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752",
+                "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416",
+                "sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f",
+                "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1",
+                "sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc",
+                "sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145",
+                "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee",
+                "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a",
+                "sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7",
+                "sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b",
+                "sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653",
+                "sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0",
+                "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90",
+                "sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29",
+                "sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6",
+                "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034",
+                "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09",
+                "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559",
+                "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639"
             ],
             "markers": "python_version < '3.11'",
-            "version": "==1.14.1"
+            "version": "==1.15.0"
         }
     },
     "develop": {
@@ -485,7 +478,7 @@
                 "sha256:37f927ea17cde7ae2d7baf832f8e80ce3777624554a653006c9144f8017fe410",
                 "sha256:762cb2bfad61f4ec8e2bdf452c7c267416f8c70dd9ecb1653fd0bbb01fa936e6"
             ],
-            "index": "pypi",
+            "markers": "python_version >= '3.5'",
             "version": "==1.0.1"
         }
     }
diff --git a/gce_rescue/bin/instance-1.log b/gce_rescue/bin/instance-1.log
deleted file mode 100644
index ea0d333..0000000
--- a/gce_rescue/bin/instance-1.log
+++ /dev/null
@@ -1,3 +0,0 @@
-2023-03-21:17:05:27,250 INFO     [__init__.py:49]      file_cache is only supported with oauth2client<4.0.0
-2023-03-26:11:27:31,975 INFO     [__init__.py:49]      file_cache is only supported with oauth2client<4.0.0
-2023-03-28:17:23:03,448 INFO     [__init__.py:49]      file_cache is only supported with oauth2client<4.0.0
diff --git a/gce_rescue/bin/rescue.py b/gce_rescue/bin/rescue.py
index 1876809..0535b6b 100755
--- a/gce_rescue/bin/rescue.py
+++ b/gce_rescue/bin/rescue.py
@@ -21,7 +21,7 @@
 
 from gce_rescue.config import process_args, set_configs
 from gce_rescue import messages
-from gce_rescue.rescue import Instance
+from gce_rescue.gce import Instance
 from gce_rescue.tasks.actions import call_tasks
 from gce_rescue.utils import read_input, set_logging
 
@@ -75,4 +75,4 @@ def main():
 
 
 if __name__ == '__main__':
-  main()
+  main()
\ No newline at end of file
diff --git a/gce_rescue/config.py b/gce_rescue/config.py
index 31ee26c..aa8ac82 100644
--- a/gce_rescue/config.py
+++ b/gce_rescue/config.py
@@ -19,7 +19,10 @@
 
 dirname = os.path.dirname(__file__)
 
+VERSION = '0.3-beta'
+
 config = {
+  'version': VERSION,
   'debug': False,
   'startup-script-file': os.path.join(dirname, 'startup-script.txt'),
   'source_guests': {
@@ -41,8 +44,8 @@ def get_config(key):
 
 def process_args():
   """ Print usage options. """
-  parser = argparse.ArgumentParser(description='GCE Rescue v0.0.2-1 - Set/Reset\
-    GCE instances to boot in rescue mode.')
+  parser = argparse.ArgumentParser(description=f'GCE Rescue v{VERSION} - \
+    Set/Reset GCE instances to boot in rescue mode.')
   parser.add_argument('-p', '--project',
                       help='The project-id that has the instance.')
   parser.add_argument('-z', '--zone', help='Zone where the instance \
diff --git a/gce_rescue/rescue.py b/gce_rescue/gce.py
similarity index 68%
rename from gce_rescue/rescue.py
rename to gce_rescue/gce.py
index f9c2a8b..bf43b56 100644
--- a/gce_rescue/rescue.py
+++ b/gce_rescue/gce.py
@@ -14,27 +14,87 @@
 
 """ Initilization Instance() with VM information. """
 
+from googleapiclient.discovery import Resource
+
 from dataclasses import dataclass, field
 from typing import Dict, List, Union
-
+from time import time
 from gce_rescue.tasks.backup import backup_metadata_items
 from gce_rescue.tasks.disks import list_disk
 from gce_rescue.tasks.pre_validations import Validations
-from gce_rescue.utils import (
-  validate_instance_mode,
-  guess_guest,
-  get_instance_info
-)
-import googleapiclient.discovery
+from gce_rescue.config import get_config
+
+
+def get_instance_info(
+  compute: Resource,
+  name: str,
+  project_data: Dict[str, str]
+) -> Dict:
+  """Set Dictionary with complete data from instances().get() from the instance.
+  https://cloud.google.com/compute/docs/reference/rest/v1/instances/get
+  Attributes:
+    compute: obj, API Object
+    instance: str, Instace name
+    project_data: dict, Dictionary containing project and zone keys to be
+      unpacked when calling the API.
+  """
+  return compute.instances().get(
+      **project_data,
+      instance = name).execute()
+
+
+def guess_guest(data: Dict) -> str:
+  """Determined which Guest OS Family is being used and select a
+  different OS for recovery disk.
+     Default: projects/debian-cloud/global/images/family/debian-11"""
+
+  guests = get_config('source_guests')
+  for disk in data['disks']:
+    if disk['boot']:
+      if 'architecture' in disk:
+        arch = disk['architecture'].lower()
+      else:
+        arch = 'x86_64'
+      guest_default = guests[arch][0]
+      guest_name = guest_default.split('/')[-1]
+      for lic in disk['licenses']:
+        if guest_name in lic:
+          guest_default = guests[arch][1]
+  return guest_default
+
+
+def validate_instance_mode(data: Dict) -> Dict:
+  """Validate if the instance is already configured as rescue mode."""
+
+  result = {
+      'rescue-mode': False,
+      'ts': generate_ts()
+  }
+  if 'metadata' in data and  'items' in data['metadata']:
+    metadata = data['metadata']
+    for item in metadata['items']:
+      if item['key'] == 'rescue-mode':
+        result = {
+          'rescue-mode': True,
+          'ts': item['value']
+        }
+
+  return result
+
+def generate_ts() -> int:
+  """Get the current timestamp to be used as unique ID
+  during this execution."""
+  return int(time())
+
 
 @dataclass
-class Instance:
+class Instance(Resource):
   """Initialize instance."""
   zone: str
   name: str
   project: str = None
   test_mode: bool = field(default_factory=False)
-  compute: googleapiclient.discovery.Resource = field(init=False)
+  compute: Resource = field(init=False)
   data: Dict[str, Union[str, int]] = field(init=False)
   ts: int = field(init=False)
   _status: str = ''
diff --git a/gce_rescue/messages.py b/gce_rescue/messages.py
index 34881b3..c46a33d 100644
--- a/gce_rescue/messages.py
+++ b/gce_rescue/messages.py
@@ -14,7 +14,7 @@
 
 """ List of messages to inform and educate the user. """
 
-from gce_rescue.rescue import Instance
+from gce_rescue.gce import Instance
 
 def tip_connect_ssh(vm: Instance) -> str:
   return (f'└── Your instance is READY! You can now connect your instance '
diff --git a/gce_rescue/multitasks.py b/gce_rescue/multitasks.py
deleted file mode 100644
index e894347..0000000
--- a/gce_rescue/multitasks.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright 2021 Google LLC
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-""" Class to handle multithread tasks. """
-
-from threading import Thread
-
-class Handler(Thread):
-  """Handler for multithread tasks."""
-
-  def __init__(
-      self,
-      group=None,
-      target=None,
-      name=None,
-      args=None,
-      kwargs=None
-    ):
-
-    if not args:
-      args = ()
-
-    if not kwargs:
-      kwargs = {}
-
-    Thread.__init__(self, group, target, name, args, kwargs)
-    self._result = None
-
-  def run(self):
-    if self._target is not None:
-      self._result = self._target(*self._args, **self._kwargs)
-
-  def result(self, *args):
-    Thread.join(self, *args)
-    return self._result
diff --git a/gce_rescue/tasks/actions.py b/gce_rescue/tasks/actions.py
index 587a740..610a78c 100644
--- a/gce_rescue/tasks/actions.py
+++ b/gce_rescue/tasks/actions.py
@@ -14,10 +14,10 @@
 
 """ List of ordered tasks to be executed when set/reset VM rescue mode. """
 
-from typing import Dict
+from typing import List
 import logging
 
-from gce_rescue.rescue import Instance
+from gce_rescue.gce import Instance
 from gce_rescue.tasks.disks import (
   config_rescue_disks,
   restore_original_disk,
@@ -35,7 +35,7 @@
 
 _logger = logging.getLogger(__name__)
 
-def _list_tasks(vm: Instance, action: str) -> Dict:
+def _list_tasks(vm: Instance, action: str) -> List:
   """ List tasks, by order, per operation
     operations (str):
       1. set_rescue_mode
@@ -113,7 +113,7 @@ def _list_tasks(vm: Instance, action: str) -> Dict:
 
   if action not in all_tasks:
     _logger.info(f'Unable to find "{action}".')
-    raise Exception(ValueError)
+    raise ValueError()
   return all_tasks[action]
 
 
diff --git a/gce_rescue/tasks/backup.py b/gce_rescue/tasks/backup.py
index 90fabcc..e08ee23 100644
--- a/gce_rescue/tasks/backup.py
+++ b/gce_rescue/tasks/backup.py
@@ -15,7 +15,7 @@
 """ Different operations to guarantee VM disks backup, before performing
     any modifications."""
 
-from gce_rescue.utils import wait_for_operation
+from gce_rescue.tasks.keeper import wait_for_operation
 from typing import Dict, List
 import logging
 
diff --git a/gce_rescue/tasks/disks.py b/gce_rescue/tasks/disks.py
index d487580..bc19a84 100644
--- a/gce_rescue/tasks/disks.py
+++ b/gce_rescue/tasks/disks.py
@@ -19,9 +19,9 @@
 
 import googleapiclient.errors
 
-from gce_rescue.utils import wait_for_operation
+from gce_rescue.tasks.keeper import wait_for_operation
 from gce_rescue.tasks.backup import  backup
-from gce_rescue.multitasks import Handler
+from gce_rescue.utils import ThreadHandler as Handler
 
 _logger = logging.getLogger(__name__)
 
diff --git a/gce_rescue/tasks/keeper.py b/gce_rescue/tasks/keeper.py
new file mode 100644
index 0000000..4dc870b
--- /dev/null
+++ b/gce_rescue/tasks/keeper.py
@@ -0,0 +1,66 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# pylint: disable=broad-exception-raised
+
+"""keeper that the progress of the tasks. """
+
+import googleapiclient.discovery
+from time import sleep
+from typing import Dict
+import logging
+import json
+
+_logger = logging.getLogger(__name__)
+
+
+def wait_for_operation(
+  instance_obj: googleapiclient.discovery.Resource,
+  oper: Dict
+) -> Dict:
+  """ Creating poll to wait the operation to finish. """
+
+  while True:
+    if oper['status'] == 'DONE':
+      _logger.info('done.')
+      if 'error' in oper:
+        raise Exception(oper['error'])
+      return oper
+
+    oper = instance_obj.compute.zoneOperations().get(
+      **instance_obj.project_data,
+      operation = oper['name']).execute()
+    sleep(1)
+
+def wait_for_os_boot(vm: googleapiclient.discovery.Resource) -> bool:
+  """Wait guest OS to complete the boot proccess."""
+
+  timeout = 60
+  wait_time = 2
+  end_string = f'END:{vm.ts}'
+  _logger.info('Waiting startup-script to complete.')
+  while True:
+    result = vm.compute.instances().getSerialPortOutput(
+      **vm.project_data,
+      instance = vm.name
+    ).execute()
+
+    if end_string in json.dumps(result):
+      _logger.info('startup-script has ended.')
+      return True
+
+    sleep(wait_time)
+    timeout -= wait_time
+    if not timeout:
+      return False
\ No newline at end of file
diff --git a/gce_rescue/tasks/metadata.py b/gce_rescue/tasks/metadata.py
index 6320385..e08dd0b 100644
--- a/gce_rescue/tasks/metadata.py
+++ b/gce_rescue/tasks/metadata.py
@@ -15,7 +15,7 @@
 """ Different functions to modify VM custom metadata. """
 
 from gce_rescue.config import get_config
-from gce_rescue.utils import wait_for_operation, wait_for_os_boot
+from gce_rescue.tasks.keeper import wait_for_operation, wait_for_os_boot
 from typing import Dict
 import logging
 
diff --git a/gce_rescue/tasks/operations.py b/gce_rescue/tasks/operations.py
index dcf0871..8ad0ffe 100644
--- a/gce_rescue/tasks/operations.py
+++ b/gce_rescue/tasks/operations.py
@@ -14,8 +14,8 @@
 
 """ Standard VM operations. """
 
-from gce_rescue.rescue import Instance
-from gce_rescue.utils import wait_for_operation
+from gce_rescue.gce import Instance
+from gce_rescue.tasks.keeper import wait_for_operation
 import logging
 
 _logger = logging.getLogger(__name__)
diff --git a/gce_rescue/tasks/pre_validations.py b/gce_rescue/tasks/pre_validations.py
index 5c1a981..b8f36a4 100644
--- a/gce_rescue/tasks/pre_validations.py
+++ b/gce_rescue/tasks/pre_validations.py
@@ -18,6 +18,7 @@
 
 from dataclasses import dataclass, field
 import googleapiclient.discovery
+from gce_rescue.tasks.validations.authorization import authorize_check
 from gce_rescue.tasks.validations.authentication import (
   authenticate_check,
   project_name
@@ -42,6 +43,10 @@ def _authentication(self):
       test_mode = self.test_mode,
     )
 
+  def __post_init__(self):
+    if not self.test_mode:
+      authorize_check(project = self.project)
+
   @property
   def compute(self) -> googleapiclient.discovery.Resource:
     return self._authentication()
diff --git a/gce_rescue/tasks/validations/api.py b/gce_rescue/tasks/validations/api.py
new file mode 100644
index 0000000..a85d4fd
--- /dev/null
+++ b/gce_rescue/tasks/validations/api.py
@@ -0,0 +1,44 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+""" Common API objects """
+import googleapiclient
+import google_auth_httplib2
+import httplib2
+
+from google.oauth2.credentials import Credentials
+from googleapiclient.discovery import Resource
+
+from gce_rescue.config import VERSION
+
+def api_service(
+    service: str,
+    version: str,
+    credentials: Credentials) -> Resource:
+
+  def _builder(http, *args, **kwargs):
+    # google api client is not thread safe
+    # https://github.com/googleapis/google-api-python-client/blob/main/docs/thread_safety.md
+    del http
+    headers = kwargs.setdefault('headers',{})
+    headers['user-agent'] = f'gce_rescue-{VERSION}'
+    auth_http = google_auth_httplib2.AuthorizedHttp(credentials,
+                                                   http=httplib2.Http())
+    return googleapiclient.http.HttpRequest(auth_http, *args, **kwargs)
+
+  service_ = googleapiclient.discovery.build(service, version,
+                        cache_discovery=False,
+                        credentials=credentials,
+                        requestBuilder=_builder)
+  return service_
diff --git a/gce_rescue/tasks/validations/authentication.py b/gce_rescue/tasks/validations/authentication.py
index 0e729f3..db75b55 100644
--- a/gce_rescue/tasks/validations/authentication.py
+++ b/gce_rescue/tasks/validations/authentication.py
@@ -13,9 +13,11 @@
 # limitations under the License.
 
 """ Authentication validation to be called from ../pre_validations.py """
-import googleapiclient.discovery
 import google.auth
 import sys
+
+from googleapiclient.discovery import Resource
+from gce_rescue.tasks.validations.api import api_service
 from gce_rescue.test.mocks import mock_api_object
 
 PROJECT = ''
@@ -41,7 +43,7 @@ def authenticate_check(
   instance_name: str,
   project: str = None,
   test_mode: bool = False
-) -> googleapiclient.discovery.Resource:
+) -> Resource:
   global PROJECT
   PROJECT = project
   if test_mode:
@@ -50,11 +52,12 @@ def authenticate_check(
   credentials = _get_auth()
   if not credentials:
     return False
-  service = googleapiclient.discovery.build(
-    'compute',
-    'v1',
-    credentials = credentials
-  )
+  # service = googleapiclient.discovery.build(
+  #   'compute',
+  #   'v1',
+  #   credentials = credentials
+  # )
+  service =  api_service('compute', 'v1', credentials)
   request = service.instances().get(
 		project = PROJECT,
 		zone = zone,
diff --git a/gce_rescue/tasks/validations/authorization.py b/gce_rescue/tasks/validations/authorization.py
new file mode 100644
index 0000000..a46dece
--- /dev/null
+++ b/gce_rescue/tasks/validations/authorization.py
@@ -0,0 +1,51 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+Authorization validation to be called from ../pre_validations.py
+Permissions:
+  compute.instances.stop
+  compute.instances.start
+  compute.instances.attachDisk
+  compute.instances.detachDisk
+  compute.images.useReadOnly
+  compute.disks.use
+  compute.disks.setLabels
+  compute.snapshots.create
+  compute.disks.createSnapshot
+  compute.instances.setMetadata
+  compute.instances.setLabels
+"""
+import google.auth
+from gce_rescue.tasks.validations.api import api_service
+
+def authorize_check(project: str = None) -> bool:
+
+  permissions_list = ['compute.snapshots.create']
+  body_data = {'permissions': permissions_list}
+  credentials, project_id = google.auth.default()
+
+  if not project:
+    project = project_id
+
+  service = api_service('cloudresourcemanager', 'v1', credentials)
+  result = service.projects().testIamPermissions(
+    resource = project,
+    body =  body_data
+  ).execute()
+
+  if permissions_list != result['permissions']:
+    raise PermissionError()
+
+  return True
diff --git a/gce_rescue/utils.py b/gce_rescue/utils.py
index adf7da3..156124f 100644
--- a/gce_rescue/utils.py
+++ b/gce_rescue/utils.py
@@ -16,15 +16,13 @@
 
 """ List of classes and functions to be used across the code. """
 
-import googleapiclient.discovery
-
-from time import time, sleep
-from typing import Dict
-from gce_rescue.config import get_config
+from time import sleep
 import logging
 import multiprocessing
+from threading import Thread
 import sys
-import json
+from gce_rescue.config import get_config
+
 
 _logger = logging.getLogger(__name__)
 
@@ -88,105 +86,35 @@ def _print(self):
       file=sys.stderr,
       flush=True)
 
-def get_instance_info(
-  compute: googleapiclient.discovery.Resource,
-  name: str,
-  project_data: Dict[str, str]
-) -> Dict:
-  """Set Dictionary with complete data from instances().get() from the instance.
-  https://cloud.google.com/compute/docs/reference/rest/v1/instances/get
-  Attributes:
-    compute: obj, API Object
-    instance: str, Instace name
-    project_data: dict, Dictionary containing project and zone keys to be
-      unpacked when calling the API.
-  """
-  return compute.instances().get(
-      **project_data,
-      instance = name).execute()
-
-def generate_ts() -> int:
-  """Get the current timestamp to be used as unique ID
-  during this execution."""
-  return int(time())
-
-def validate_instance_mode(data: Dict) -> Dict:
-  """Validate if the instance is already configured as rescue mode."""
-
-  result = {
-      'rescue-mode': False,
-      'ts': generate_ts()
-  }
-  if 'metadata' in data and  'items' in data['metadata']:
-    metadata = data['metadata']
-    for item in metadata['items']:
-      if item['key'] == 'rescue-mode':
-        result = {
-          'rescue-mode': True,
-          'ts': item['value']
-        }
-
-  return result
-
-def guess_guest(data: Dict) -> str:
-  """Determined which Guest OS Family is being used and select a
-  different OS for recovery disk.
-     Default: projects/debian-cloud/global/images/family/debian-11"""
-
-  guests = get_config('source_guests')
-  for disk in data['disks']:
-    if disk['boot']:
-      if 'architecture' in disk:
-        arch = disk['architecture'].lower()
-      else:
-        arch = 'x86_64'
-      guest_default = guests[arch][0]
-      guest_name = guest_default.split('/')[-1]
-      for lic in disk['licenses']:
-        if guest_name in lic:
-          guest_default = guests[arch][1]
-  return guest_default
-
-
-def wait_for_operation(
-  instance_obj: googleapiclient.discovery.Resource,
-  oper: Dict
-) -> Dict:
-  """ Creating poll to wait the operation to finish. """
-
-  while True:
-    if oper['status'] == 'DONE':
-      _logger.info('done.')
-      if 'error' in oper:
-        raise Exception(oper['error'])
-      return oper
-
-    oper = instance_obj.compute.zoneOperations().get(
-      **instance_obj.project_data,
-      operation = oper['name']).execute()
-    sleep(1)
-
-def wait_for_os_boot(vm: googleapiclient.discovery.Resource) -> bool:
-  """Wait guest OS to complete the boot proccess."""
-
-  timeout = 60
-  wait_time = 2
-  end_string = f'END:{vm.ts}'
-  _logger.info('Waiting startup-script to complete.')
-  while True:
-    result = vm.compute.instances().getSerialPortOutput(
-      **vm.project_data,
-      instance = vm.name
-    ).execute()
-
-    if end_string in json.dumps(result):
-      _logger.info('startup-script has ended.')
-      return True
-
-    sleep(wait_time)
-    timeout -= wait_time
-    if not timeout:
-      return False
+
+class ThreadHandler(Thread):
+  """Handler for multithread tasks."""
+
+  def __init__(
+      self,
+      group=None,
+      target=None,
+      name=None,
+      args=None,
+      kwargs=None
+    ):
+
+    if not args:
+      args = ()
+
+    if not kwargs:
+      kwargs = {}
+
+    Thread.__init__(self, group, target, name, args, kwargs)
+    self._result = None
+
+  def run(self):
+    if self._target is not None:
+      self._result = self._target(*self._args, **self._kwargs)
+
+  def result(self, *args):
+    Thread.join(self, *args)
+    return self._result
 
 
 def set_logging(vm_name: str) -> None:
@@ -203,6 +131,7 @@ def set_logging(vm_name: str) -> None:
     datefmt='%Y-%m-%d:%H:%M:%S',
     level=log_level)
 
+
 def read_input(msg: str) -> None:
   """Read user input if --force is not provided."""
   print(msg, end='')
@@ -211,3 +140,4 @@ def read_input(msg: str) -> None:
   if input_answer.upper() != 'Y':
     print(f'got input: "{input_answer}". Aborting')
     sys.exit(1)
+    
\ No newline at end of file
diff --git a/setup.py b/setup.py
index 113ae8b..87cb78f 100755
--- a/setup.py
+++ b/setup.py
@@ -19,6 +19,8 @@
 from setuptools import setup, find_packages
 from os import path
 
+from gce_rescue.config import VERSION
+
 my_pwd = path.abspath(path.dirname(__file__))
 
 # Get the long description from the README file
@@ -31,7 +33,7 @@
 
 setup(
   name = 'gce-rescue',
-  version = '0.0.2-1',
+  version = VERSION,
   description='GCE Rescue - Boot your GCE VM in rescue mode.',
   url = 'https://github.com/googlecloudplatform/gce-rescue',
   author = 'Halley de Souza',
@@ -51,10 +53,14 @@
         ],
     },
   classifiers = [
-    'Development Status :: 3 - Alpha',
     'License :: OSI Approved :: Apache Software License',
     'Operating System :: OS Independent',
-    'Programming Language :: Python :: 3',
+    'Programming Language :: Python :: 3.7',
+    'Programming Language :: Python :: 3.8',
+    'Programming Language :: Python :: 3.9',
+    'Programming Language :: Python :: 3.10',
+    'Programming Language :: Python :: 3.11',
+    'Programming Language :: Python :: 3.12',
     'Topic :: System :: Boot',
     'Topic :: System :: Boot :: Init',
     'Topic :: System :: Recovery Tools',


Test patch:
diff --git a/gce_rescue/rescue_test.py b/gce_rescue/gce_test.py
similarity index 98%
rename from gce_rescue/rescue_test.py
rename to gce_rescue/gce_test.py
index e63c240..6001862 100644
--- a/gce_rescue/rescue_test.py
+++ b/gce_rescue/gce_test.py
@@ -15,7 +15,7 @@
 """Test code for rescue.py."""
 
 from absl.testing import absltest
-from gce_rescue.rescue import Instance
+from gce_rescue.gce import Instance
 from gce_rescue.test.mocks import (
   mock_api_object,
   MOCK_TEST_VM,
diff --git a/gce_rescue/messages_test.py b/gce_rescue/messages_test.py
index 4636409..2608ea0 100644
--- a/gce_rescue/messages_test.py
+++ b/gce_rescue/messages_test.py
@@ -16,7 +16,7 @@
 
 from absl.testing import absltest
 from gce_rescue import messages
-from gce_rescue.rescue import Instance
+from gce_rescue.gce import Instance
 from gce_rescue.test.mocks import mock_api_object, MOCK_TEST_VM
 
 
diff --git a/gce_rescue/tasks/backup_test.py b/gce_rescue/tasks/backup_test.py
index 9580cf8..8f886d8 100644
--- a/gce_rescue/tasks/backup_test.py
+++ b/gce_rescue/tasks/backup_test.py
@@ -17,7 +17,7 @@
 from absl.testing import absltest
 from gce_rescue.tasks import backup
 from gce_rescue.test.mocks import mock_api_object, MOCK_TEST_VM
-from gce_rescue.rescue import Instance
+from gce_rescue.gce import Instance
 
 
 class BackupTest(absltest.TestCase):
diff --git a/gce_rescue/tasks/disks_test.py b/gce_rescue/tasks/disks_test.py
index 0c458e4..940e7a4 100644
--- a/gce_rescue/tasks/disks_test.py
+++ b/gce_rescue/tasks/disks_test.py
@@ -17,7 +17,7 @@
 from absl.testing import absltest
 from absl import logging
 
-from gce_rescue.rescue import Instance
+from gce_rescue.gce import Instance
 from gce_rescue.tasks import disks
 from gce_rescue.test.mocks import (
   mock_api_object,
diff --git a/gce_rescue/tasks/metadata_test.py b/gce_rescue/tasks/metadata_test.py
index 7b2b8b8..cc1abe9 100644
--- a/gce_rescue/tasks/metadata_test.py
+++ b/gce_rescue/tasks/metadata_test.py
@@ -15,9 +15,8 @@
 """Test code for metadata.py."""
 
 from absl.testing import absltest
-from absl import logging
 
-from gce_rescue.rescue import Instance
+from gce_rescue.gce import Instance
 from gce_rescue.tasks import metadata
 from gce_rescue.test.mocks import  mock_api_object, MOCK_TEST_VM
 
diff --git a/gce_rescue/tasks/operations_test.py b/gce_rescue/tasks/operations_test.py
index c2c7d9c..a88de66 100644
--- a/gce_rescue/tasks/operations_test.py
+++ b/gce_rescue/tasks/operations_test.py
@@ -15,7 +15,7 @@
 """Test code for operations.py."""
 
 from absl.testing import absltest
-from gce_rescue.rescue import Instance
+from gce_rescue.gce import Instance
 from gce_rescue.tasks.operations import start_instance, stop_instance
 from gce_rescue.test.mocks import mock_api_object, MOCK_TEST_VM
 
diff --git a/gce_rescue/multitasks_test.py b/gce_rescue/utils_test.py
similarity index 89%
rename from gce_rescue/multitasks_test.py
rename to gce_rescue/utils_test.py
index 395fb30..9e9d2ae 100644
--- a/gce_rescue/multitasks_test.py
+++ b/gce_rescue/utils_test.py
@@ -15,7 +15,7 @@
 """ Multitask test code """
 
 from absl.testing import absltest
-from gce_rescue.multitasks import Handler
+from gce_rescue.utils import ThreadHandler as Handler
 import time
 
 OUTPUT1 = 'task1 done'
@@ -31,8 +31,8 @@ class MultitasksTest(absltest.TestCase):
 
   @classmethod
   def task1(cls):
-    for i in range(0, 3):
-      print(f'task 1, time {i}')
+    for _ in range(0, 3):
+      # print(f'task 1, time {i}')
       time.sleep(0.001)
     MultitasksTest.status['task1_done'] = True
     return OUTPUT1
@@ -40,8 +40,8 @@ def task1(cls):
 
   @classmethod
   def task2(cls):
-    for i in range(0, 3):
-      print(f'task 2, time {i}')
+    for _ in range(0, 3):
+      # print(f'task 2, time {i}')
       time.sleep(0.001)
     MultitasksTest.status['task2_done'] = True
     return OUTPUT2