opencloudtool 0.6.1__tar.gz → 0.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/Cargo.lock +95 -19
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/Cargo.toml +9 -8
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/PKG-INFO +1 -1
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/crates/oct-cloud/README.md +4 -0
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/crates/oct-cloud/src/aws/types.rs +146 -17
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/crates/oct-cloud/src/infra/graph.rs +45 -134
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/crates/oct-cloud/src/infra/resource.rs +12 -12
- {opencloudtool-0.6.1/crates/oct-orchestrator → opencloudtool-0.7.0/crates/oct-ctl-sdk}/README.md +4 -0
- {opencloudtool-0.6.1/crates/oct-ctl-sdk → opencloudtool-0.7.0/crates/oct-orchestrator}/README.md +4 -0
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/crates/oct-orchestrator/src/lib.rs +14 -30
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/crates/oct-py/uv.lock +1 -1
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/pyproject.toml +1 -1
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/README.md +0 -0
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/crates/oct-cloud/Cargo.toml +0 -0
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/crates/oct-cloud/src/aws/client.rs +0 -0
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/crates/oct-cloud/src/aws/mod.rs +0 -0
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/crates/oct-cloud/src/aws/resource.rs +0 -0
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/crates/oct-cloud/src/infra/mod.rs +0 -0
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/crates/oct-cloud/src/infra/state.rs +0 -0
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/crates/oct-cloud/src/lib.rs +0 -0
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/crates/oct-cloud/src/resource.rs +0 -0
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/crates/oct-ctl-sdk/Cargo.toml +0 -0
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/crates/oct-ctl-sdk/src/lib.rs +0 -0
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/crates/oct-orchestrator/Cargo.toml +0 -0
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/crates/oct-orchestrator/src/backend.rs +0 -0
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/crates/oct-orchestrator/src/config.rs +0 -0
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/crates/oct-orchestrator/src/scheduler.rs +0 -0
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/crates/oct-orchestrator/src/user_state.rs +0 -0
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/crates/oct-py/.python-version +0 -0
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/crates/oct-py/Cargo.toml +0 -0
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/crates/oct-py/README.md +0 -0
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/crates/oct-py/python/opencloudtool/__init__.py +0 -0
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/crates/oct-py/python/opencloudtool/py_api.py +0 -0
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/crates/oct-py/src/lib.rs +0 -0
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/python/opencloudtool/__init__.py +0 -0
- {opencloudtool-0.6.1 → opencloudtool-0.7.0}/python/opencloudtool/py_api.py +0 -0
|
@@ -82,6 +82,48 @@ dependencies = [
|
|
|
82
82
|
"windows-sys 0.59.0",
|
|
83
83
|
]
|
|
84
84
|
|
|
85
|
+
[[package]]
|
|
86
|
+
name = "askama"
|
|
87
|
+
version = "0.14.0"
|
|
88
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
89
|
+
checksum = "f75363874b771be265f4ffe307ca705ef6f3baa19011c149da8674a87f1b75c4"
|
|
90
|
+
dependencies = [
|
|
91
|
+
"askama_derive",
|
|
92
|
+
"itoa",
|
|
93
|
+
"percent-encoding",
|
|
94
|
+
"serde",
|
|
95
|
+
"serde_json",
|
|
96
|
+
]
|
|
97
|
+
|
|
98
|
+
[[package]]
|
|
99
|
+
name = "askama_derive"
|
|
100
|
+
version = "0.14.0"
|
|
101
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
102
|
+
checksum = "129397200fe83088e8a68407a8e2b1f826cf0086b21ccdb866a722c8bcd3a94f"
|
|
103
|
+
dependencies = [
|
|
104
|
+
"askama_parser",
|
|
105
|
+
"basic-toml",
|
|
106
|
+
"memchr",
|
|
107
|
+
"proc-macro2",
|
|
108
|
+
"quote",
|
|
109
|
+
"rustc-hash 2.1.1",
|
|
110
|
+
"serde",
|
|
111
|
+
"serde_derive",
|
|
112
|
+
"syn",
|
|
113
|
+
]
|
|
114
|
+
|
|
115
|
+
[[package]]
|
|
116
|
+
name = "askama_parser"
|
|
117
|
+
version = "0.14.0"
|
|
118
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
119
|
+
checksum = "d6ab5630b3d5eaf232620167977f95eb51f3432fc76852328774afbd242d4358"
|
|
120
|
+
dependencies = [
|
|
121
|
+
"memchr",
|
|
122
|
+
"serde",
|
|
123
|
+
"serde_derive",
|
|
124
|
+
"winnow",
|
|
125
|
+
]
|
|
126
|
+
|
|
85
127
|
[[package]]
|
|
86
128
|
name = "assert-json-diff"
|
|
87
129
|
version = "2.0.2"
|
|
@@ -651,9 +693,9 @@ dependencies = [
|
|
|
651
693
|
|
|
652
694
|
[[package]]
|
|
653
695
|
name = "axum"
|
|
654
|
-
version = "0.8.
|
|
696
|
+
version = "0.8.7"
|
|
655
697
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
656
|
-
checksum = "
|
|
698
|
+
checksum = "5b098575ebe77cb6d14fc7f32749631a6e44edbef6b796f89b020e99ba20d425"
|
|
657
699
|
dependencies = [
|
|
658
700
|
"axum-core",
|
|
659
701
|
"bytes",
|
|
@@ -735,6 +777,15 @@ version = "1.8.0"
|
|
|
735
777
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
736
778
|
checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba"
|
|
737
779
|
|
|
780
|
+
[[package]]
|
|
781
|
+
name = "basic-toml"
|
|
782
|
+
version = "0.1.10"
|
|
783
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
784
|
+
checksum = "ba62675e8242a4c4e806d12f11d136e626e6c8361d6b829310732241652a178a"
|
|
785
|
+
dependencies = [
|
|
786
|
+
"serde",
|
|
787
|
+
]
|
|
788
|
+
|
|
738
789
|
[[package]]
|
|
739
790
|
name = "bindgen"
|
|
740
791
|
version = "0.69.5"
|
|
@@ -752,7 +803,7 @@ dependencies = [
|
|
|
752
803
|
"proc-macro2",
|
|
753
804
|
"quote",
|
|
754
805
|
"regex",
|
|
755
|
-
"rustc-hash",
|
|
806
|
+
"rustc-hash 1.1.0",
|
|
756
807
|
"shlex",
|
|
757
808
|
"syn",
|
|
758
809
|
"which",
|
|
@@ -879,9 +930,9 @@ dependencies = [
|
|
|
879
930
|
|
|
880
931
|
[[package]]
|
|
881
932
|
name = "clap"
|
|
882
|
-
version = "4.5.
|
|
933
|
+
version = "4.5.53"
|
|
883
934
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
884
|
-
checksum = "
|
|
935
|
+
checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8"
|
|
885
936
|
dependencies = [
|
|
886
937
|
"clap_builder",
|
|
887
938
|
"clap_derive",
|
|
@@ -889,9 +940,9 @@ dependencies = [
|
|
|
889
940
|
|
|
890
941
|
[[package]]
|
|
891
942
|
name = "clap_builder"
|
|
892
|
-
version = "4.5.
|
|
943
|
+
version = "4.5.53"
|
|
893
944
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
894
|
-
checksum = "
|
|
945
|
+
checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00"
|
|
895
946
|
dependencies = [
|
|
896
947
|
"anstream",
|
|
897
948
|
"anstyle",
|
|
@@ -2078,9 +2129,9 @@ dependencies = [
|
|
|
2078
2129
|
|
|
2079
2130
|
[[package]]
|
|
2080
2131
|
name = "mockall"
|
|
2081
|
-
version = "0.
|
|
2132
|
+
version = "0.14.0"
|
|
2082
2133
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2083
|
-
checksum = "
|
|
2134
|
+
checksum = "f58d964098a5f9c6b63d0798e5372fd04708193510a7af313c22e9f29b7b620b"
|
|
2084
2135
|
dependencies = [
|
|
2085
2136
|
"cfg-if",
|
|
2086
2137
|
"downcast",
|
|
@@ -2092,9 +2143,9 @@ dependencies = [
|
|
|
2092
2143
|
|
|
2093
2144
|
[[package]]
|
|
2094
2145
|
name = "mockall_derive"
|
|
2095
|
-
version = "0.
|
|
2146
|
+
version = "0.14.0"
|
|
2096
2147
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2097
|
-
checksum = "
|
|
2148
|
+
checksum = "ca41ce716dda6a9be188b385aa78ee5260fc25cd3802cb2a8afdc6afbe6b6dbf"
|
|
2098
2149
|
dependencies = [
|
|
2099
2150
|
"cfg-if",
|
|
2100
2151
|
"proc-macro2",
|
|
@@ -2194,7 +2245,7 @@ dependencies = [
|
|
|
2194
2245
|
|
|
2195
2246
|
[[package]]
|
|
2196
2247
|
name = "oct-cli"
|
|
2197
|
-
version = "0.
|
|
2248
|
+
version = "0.7.0"
|
|
2198
2249
|
dependencies = [
|
|
2199
2250
|
"assert_cmd",
|
|
2200
2251
|
"clap",
|
|
@@ -2206,7 +2257,7 @@ dependencies = [
|
|
|
2206
2257
|
|
|
2207
2258
|
[[package]]
|
|
2208
2259
|
name = "oct-cloud"
|
|
2209
|
-
version = "0.
|
|
2260
|
+
version = "0.7.0"
|
|
2210
2261
|
dependencies = [
|
|
2211
2262
|
"aws-config",
|
|
2212
2263
|
"aws-sdk-ec2",
|
|
@@ -2226,7 +2277,7 @@ dependencies = [
|
|
|
2226
2277
|
|
|
2227
2278
|
[[package]]
|
|
2228
2279
|
name = "oct-ctl"
|
|
2229
|
-
version = "0.
|
|
2280
|
+
version = "0.7.0"
|
|
2230
2281
|
dependencies = [
|
|
2231
2282
|
"axum",
|
|
2232
2283
|
"log",
|
|
@@ -2242,7 +2293,7 @@ dependencies = [
|
|
|
2242
2293
|
|
|
2243
2294
|
[[package]]
|
|
2244
2295
|
name = "oct-ctl-sdk"
|
|
2245
|
-
version = "0.
|
|
2296
|
+
version = "0.7.0"
|
|
2246
2297
|
dependencies = [
|
|
2247
2298
|
"log",
|
|
2248
2299
|
"mockito",
|
|
@@ -2254,7 +2305,7 @@ dependencies = [
|
|
|
2254
2305
|
|
|
2255
2306
|
[[package]]
|
|
2256
2307
|
name = "oct-orchestrator"
|
|
2257
|
-
version = "0.
|
|
2308
|
+
version = "0.7.0"
|
|
2258
2309
|
dependencies = [
|
|
2259
2310
|
"async-trait",
|
|
2260
2311
|
"log",
|
|
@@ -2270,9 +2321,25 @@ dependencies = [
|
|
|
2270
2321
|
"toml",
|
|
2271
2322
|
]
|
|
2272
2323
|
|
|
2324
|
+
[[package]]
|
|
2325
|
+
name = "oct-platform"
|
|
2326
|
+
version = "0.7.0"
|
|
2327
|
+
dependencies = [
|
|
2328
|
+
"askama",
|
|
2329
|
+
"axum",
|
|
2330
|
+
"reqwest",
|
|
2331
|
+
"serde",
|
|
2332
|
+
"serde_json",
|
|
2333
|
+
"tokio",
|
|
2334
|
+
"toml",
|
|
2335
|
+
"tower-http",
|
|
2336
|
+
"tracing",
|
|
2337
|
+
"tracing-subscriber",
|
|
2338
|
+
]
|
|
2339
|
+
|
|
2273
2340
|
[[package]]
|
|
2274
2341
|
name = "oct-py"
|
|
2275
|
-
version = "0.
|
|
2342
|
+
version = "0.7.0"
|
|
2276
2343
|
dependencies = [
|
|
2277
2344
|
"env_logger",
|
|
2278
2345
|
"log",
|
|
@@ -2852,6 +2919,12 @@ version = "1.1.0"
|
|
|
2852
2919
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2853
2920
|
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
|
2854
2921
|
|
|
2922
|
+
[[package]]
|
|
2923
|
+
name = "rustc-hash"
|
|
2924
|
+
version = "2.1.1"
|
|
2925
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2926
|
+
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
|
|
2927
|
+
|
|
2855
2928
|
[[package]]
|
|
2856
2929
|
name = "rustc_version"
|
|
2857
2930
|
version = "0.4.1"
|
|
@@ -3586,9 +3659,9 @@ dependencies = [
|
|
|
3586
3659
|
|
|
3587
3660
|
[[package]]
|
|
3588
3661
|
name = "tower-http"
|
|
3589
|
-
version = "0.6.
|
|
3662
|
+
version = "0.6.7"
|
|
3590
3663
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3591
|
-
checksum = "
|
|
3664
|
+
checksum = "9cf146f99d442e8e68e585f5d798ccd3cad9a7835b917e09728880a862706456"
|
|
3592
3665
|
dependencies = [
|
|
3593
3666
|
"bitflags",
|
|
3594
3667
|
"bytes",
|
|
@@ -4213,6 +4286,9 @@ name = "winnow"
|
|
|
4213
4286
|
version = "0.7.13"
|
|
4214
4287
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
4215
4288
|
checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf"
|
|
4289
|
+
dependencies = [
|
|
4290
|
+
"memchr",
|
|
4291
|
+
]
|
|
4216
4292
|
|
|
4217
4293
|
[[package]]
|
|
4218
4294
|
name = "wit-bindgen-rt"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
[workspace.package]
|
|
2
|
-
version = "0.
|
|
2
|
+
version = "0.7.0"
|
|
3
3
|
authors = ["opencloudtool Contributors"]
|
|
4
4
|
categories = ["command-line-utilities"]
|
|
5
5
|
documentation = "https://opencloudtool.com/docs"
|
|
@@ -25,11 +25,12 @@ members = ["crates/*"]
|
|
|
25
25
|
resolver = "3"
|
|
26
26
|
|
|
27
27
|
[workspace.dependencies]
|
|
28
|
-
oct-cloud = { package = "oct-cloud", path = "crates/oct-cloud", version = "0.
|
|
29
|
-
oct-orchestrator = { package = "oct-orchestrator", path = "crates/oct-orchestrator", version = "0.
|
|
30
|
-
oct-ctl-sdk = { package = "oct-ctl-sdk", path = "crates/oct-ctl-sdk", version = "0.
|
|
28
|
+
oct-cloud = { package = "oct-cloud", path = "crates/oct-cloud", version = "0.7.0" }
|
|
29
|
+
oct-orchestrator = { package = "oct-orchestrator", path = "crates/oct-orchestrator", version = "0.7.0" }
|
|
30
|
+
oct-ctl-sdk = { package = "oct-ctl-sdk", path = "crates/oct-ctl-sdk", version = "0.7.0" }
|
|
31
31
|
|
|
32
32
|
assert_cmd = "2.1.1"
|
|
33
|
+
askama = "0.14.0"
|
|
33
34
|
async-trait = "0.1.89"
|
|
34
35
|
aws-config = "1.8.3"
|
|
35
36
|
aws-sdk-ec2 = "1.154.0"
|
|
@@ -37,9 +38,9 @@ aws-sdk-ecr = "1.87.0"
|
|
|
37
38
|
aws-sdk-iam = "1.83.0"
|
|
38
39
|
aws-sdk-route53 = "1.88.0"
|
|
39
40
|
aws-sdk-s3 = "1.100.0"
|
|
40
|
-
axum = "0.8.
|
|
41
|
+
axum = "0.8.7"
|
|
41
42
|
base64 = "0.22.1"
|
|
42
|
-
clap = { version = "4.5.
|
|
43
|
+
clap = { version = "4.5.53", features = ["derive"] }
|
|
43
44
|
petgraph = "0.8.3"
|
|
44
45
|
predicates = "3.1.3"
|
|
45
46
|
serde = "1.0.228"
|
|
@@ -48,7 +49,7 @@ serde_json = "1.0.145"
|
|
|
48
49
|
tempfile = "3.23.0"
|
|
49
50
|
tera = { git = "https://github.com/minev-dev/tera.git", rev = "1e36d2f8ba66833ce9ad2b46044e21f8240b5299", version = "1.20.0" } # Contains custom logic to render variables ignoring unknown variables
|
|
50
51
|
tokio = { version = "1.48.0", features = ["full"] }
|
|
51
|
-
mockall = "0.
|
|
52
|
+
mockall = "0.14.0"
|
|
52
53
|
mockito = "1.7.0"
|
|
53
54
|
pyo3 = { version = "0.27.1", features = ["extension-module"] }
|
|
54
55
|
uuid = { version = "1.18.1", features = ["v4"] }
|
|
@@ -57,7 +58,7 @@ env_logger = "0.11.6"
|
|
|
57
58
|
toml = "0.9.8"
|
|
58
59
|
reqwest = { version = "0.12.24", features = ["json"] }
|
|
59
60
|
tower = "0.5.2"
|
|
60
|
-
tower-http = { version = "0.6.
|
|
61
|
+
tower-http = { version = "0.6.7", features = ["trace"] }
|
|
61
62
|
tracing = "0.1"
|
|
62
63
|
tracing-subscriber = { version = "0.3" }
|
|
63
64
|
grcov = "0.8.20"
|
|
@@ -230,3 +230,7 @@ Total: $92 per month
|
|
|
230
230
|
- 1 EC2 [t4g.medium](https://aws.amazon.com/ec2/pricing/on-demand/) instance ($0.0336 per hour): $25.5 per month
|
|
231
231
|
|
|
232
232
|
Total: $25.5 per month
|
|
233
|
+
|
|
234
|
+
## Repo stats
|
|
235
|
+
|
|
236
|
+

|
|
@@ -74,28 +74,81 @@ pub struct InstanceInfo {
|
|
|
74
74
|
|
|
75
75
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
76
76
|
pub enum InstanceType {
|
|
77
|
-
|
|
77
|
+
T3Nano,
|
|
78
|
+
T3Micro,
|
|
79
|
+
T3Small,
|
|
78
80
|
T3Medium,
|
|
81
|
+
T3Large,
|
|
82
|
+
T3Xlarge,
|
|
83
|
+
T32xlarge,
|
|
79
84
|
}
|
|
80
85
|
|
|
81
86
|
impl InstanceType {
|
|
82
87
|
pub fn as_str(&self) -> &str {
|
|
83
88
|
match self {
|
|
84
|
-
InstanceType::
|
|
89
|
+
InstanceType::T3Nano => "t3.nano",
|
|
90
|
+
InstanceType::T3Micro => "t3.micro",
|
|
91
|
+
InstanceType::T3Small => "t3.small",
|
|
85
92
|
InstanceType::T3Medium => "t3.medium",
|
|
93
|
+
InstanceType::T3Large => "t3.large",
|
|
94
|
+
InstanceType::T3Xlarge => "t3.xlarge",
|
|
95
|
+
InstanceType::T32xlarge => "t3.2xlarge",
|
|
86
96
|
}
|
|
87
97
|
}
|
|
88
98
|
|
|
99
|
+
/// Tries to get the smallest possible instance type for to fit requested resources
|
|
100
|
+
// NOTE: The instances list must be sorted by size from smallest to largest
|
|
101
|
+
pub fn from_resources(cpus: u32, memory: u64) -> Option<Self> {
|
|
102
|
+
let instances = [
|
|
103
|
+
Self::T3Nano,
|
|
104
|
+
Self::T3Micro,
|
|
105
|
+
Self::T3Small,
|
|
106
|
+
Self::T3Medium,
|
|
107
|
+
Self::T3Large,
|
|
108
|
+
Self::T3Xlarge,
|
|
109
|
+
Self::T32xlarge,
|
|
110
|
+
];
|
|
111
|
+
|
|
112
|
+
for instance in instances {
|
|
113
|
+
let info = instance.get_info();
|
|
114
|
+
if cpus <= info.cpus && memory <= info.memory {
|
|
115
|
+
return Some(instance);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
None
|
|
120
|
+
}
|
|
121
|
+
|
|
89
122
|
pub fn get_info(&self) -> InstanceInfo {
|
|
90
123
|
match self {
|
|
91
|
-
|
|
92
|
-
cpus:
|
|
124
|
+
Self::T3Nano => InstanceInfo {
|
|
125
|
+
cpus: 2000,
|
|
126
|
+
memory: 512,
|
|
127
|
+
},
|
|
128
|
+
Self::T3Micro => InstanceInfo {
|
|
129
|
+
cpus: 2000,
|
|
93
130
|
memory: 1024,
|
|
94
131
|
},
|
|
95
|
-
|
|
132
|
+
Self::T3Small => InstanceInfo {
|
|
133
|
+
cpus: 2000,
|
|
134
|
+
memory: 2048,
|
|
135
|
+
},
|
|
136
|
+
Self::T3Medium => InstanceInfo {
|
|
96
137
|
cpus: 2000,
|
|
97
138
|
memory: 4096,
|
|
98
139
|
},
|
|
140
|
+
Self::T3Large => InstanceInfo {
|
|
141
|
+
cpus: 2000,
|
|
142
|
+
memory: 8192,
|
|
143
|
+
},
|
|
144
|
+
Self::T3Xlarge => InstanceInfo {
|
|
145
|
+
cpus: 4000,
|
|
146
|
+
memory: 16384,
|
|
147
|
+
},
|
|
148
|
+
Self::T32xlarge => InstanceInfo {
|
|
149
|
+
cpus: 8000,
|
|
150
|
+
memory: 32768,
|
|
151
|
+
},
|
|
99
152
|
}
|
|
100
153
|
}
|
|
101
154
|
}
|
|
@@ -108,8 +161,13 @@ impl From<&str> for InstanceType {
|
|
|
108
161
|
/// Panics if the string is not a valid instance type.
|
|
109
162
|
fn from(value: &str) -> Self {
|
|
110
163
|
match value {
|
|
111
|
-
"
|
|
112
|
-
"t3.
|
|
164
|
+
"t3.nano" => Self::T3Nano,
|
|
165
|
+
"t3.micro" => Self::T3Micro,
|
|
166
|
+
"t3.small" => Self::T3Small,
|
|
167
|
+
"t3.medium" => Self::T3Medium,
|
|
168
|
+
"t3.large" => Self::T3Large,
|
|
169
|
+
"t3.xlarge" => Self::T3Xlarge,
|
|
170
|
+
"t3.2xlarge" => Self::T32xlarge,
|
|
113
171
|
_ => panic!("Invalid instance type: {value}"),
|
|
114
172
|
}
|
|
115
173
|
}
|
|
@@ -186,32 +244,32 @@ mod tests {
|
|
|
186
244
|
|
|
187
245
|
#[test]
|
|
188
246
|
fn test_instance_type_as_str() {
|
|
189
|
-
assert_eq!(InstanceType::
|
|
190
|
-
assert_eq!(InstanceType::
|
|
247
|
+
assert_eq!(InstanceType::T3Nano.as_str(), "t3.nano");
|
|
248
|
+
assert_eq!(InstanceType::T32xlarge.as_str(), "t3.2xlarge");
|
|
191
249
|
}
|
|
192
250
|
|
|
193
251
|
#[test]
|
|
194
252
|
fn test_instance_type_get_info() {
|
|
195
253
|
assert_eq!(
|
|
196
|
-
InstanceType::
|
|
254
|
+
InstanceType::T3Nano.get_info(),
|
|
197
255
|
InstanceInfo {
|
|
198
|
-
cpus:
|
|
199
|
-
memory:
|
|
256
|
+
cpus: 2000,
|
|
257
|
+
memory: 512
|
|
200
258
|
}
|
|
201
259
|
);
|
|
202
260
|
assert_eq!(
|
|
203
|
-
InstanceType::
|
|
261
|
+
InstanceType::T32xlarge.get_info(),
|
|
204
262
|
InstanceInfo {
|
|
205
|
-
cpus:
|
|
206
|
-
memory:
|
|
263
|
+
cpus: 8000,
|
|
264
|
+
memory: 32768
|
|
207
265
|
}
|
|
208
266
|
);
|
|
209
267
|
}
|
|
210
268
|
|
|
211
269
|
#[test]
|
|
212
270
|
fn test_instance_type_from_str() {
|
|
213
|
-
assert_eq!(InstanceType::from("
|
|
214
|
-
assert_eq!(InstanceType::from("t3.
|
|
271
|
+
assert_eq!(InstanceType::from("t3.nano"), InstanceType::T3Nano);
|
|
272
|
+
assert_eq!(InstanceType::from("t3.2xlarge"), InstanceType::T32xlarge);
|
|
215
273
|
}
|
|
216
274
|
|
|
217
275
|
#[test]
|
|
@@ -219,4 +277,75 @@ mod tests {
|
|
|
219
277
|
fn test_instance_type_from_str_invalid() {
|
|
220
278
|
let _ = InstanceType::from("invalid");
|
|
221
279
|
}
|
|
280
|
+
|
|
281
|
+
#[test]
|
|
282
|
+
fn test_from_resources_fits_t3_nano_small_request() {
|
|
283
|
+
assert_eq!(
|
|
284
|
+
InstanceType::from_resources(500, 512),
|
|
285
|
+
Some(InstanceType::T3Nano)
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
#[test]
|
|
290
|
+
fn test_from_resources_fits_t3_nano_exact_request() {
|
|
291
|
+
assert_eq!(
|
|
292
|
+
InstanceType::from_resources(2000, 512),
|
|
293
|
+
Some(InstanceType::T3Nano)
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
#[test]
|
|
298
|
+
fn test_from_resources_fits_t3_micro_mem_overflow() {
|
|
299
|
+
assert_eq!(
|
|
300
|
+
InstanceType::from_resources(2000, 513),
|
|
301
|
+
Some(InstanceType::T3Micro)
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
#[test]
|
|
306
|
+
fn test_from_resources_fits_t3_medium_cpu_overflow() {
|
|
307
|
+
assert_eq!(
|
|
308
|
+
InstanceType::from_resources(2001, 8192),
|
|
309
|
+
Some(InstanceType::T3Xlarge)
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
#[test]
|
|
314
|
+
fn test_from_resources_fits_t3_xlarge_exact() {
|
|
315
|
+
assert_eq!(
|
|
316
|
+
InstanceType::from_resources(4000, 16384),
|
|
317
|
+
Some(InstanceType::T3Xlarge)
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
#[test]
|
|
322
|
+
fn test_from_resources_fits_t3_2xlarge_mem_overflow() {
|
|
323
|
+
assert_eq!(
|
|
324
|
+
InstanceType::from_resources(4000, 16385),
|
|
325
|
+
Some(InstanceType::T32xlarge)
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
#[test]
|
|
330
|
+
fn test_from_resources_fits_t3_2xlarge_exact_request() {
|
|
331
|
+
assert_eq!(
|
|
332
|
+
InstanceType::from_resources(8000, 32768),
|
|
333
|
+
Some(InstanceType::T32xlarge)
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
#[test]
|
|
338
|
+
fn test_from_resources_no_fit_cpu_overflow() {
|
|
339
|
+
assert_eq!(InstanceType::from_resources(8001, 32768), None);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
#[test]
|
|
343
|
+
fn test_from_resources_no_fit_mem_overflow() {
|
|
344
|
+
assert_eq!(InstanceType::from_resources(8000, 32769), None);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
#[test]
|
|
348
|
+
fn test_from_resources_no_fit_large_request() {
|
|
349
|
+
assert_eq!(InstanceType::from_resources(u32::MAX, u64::MAX), None);
|
|
350
|
+
}
|
|
222
351
|
}
|
|
@@ -66,7 +66,6 @@ impl GraphManager {
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
pub fn get_spec_graph(
|
|
69
|
-
number_of_instances: u32,
|
|
70
69
|
instance_type: &types::InstanceType,
|
|
71
70
|
domain_name: Option<String>,
|
|
72
71
|
) -> Graph<SpecNode, String> {
|
|
@@ -167,16 +166,11 @@ impl GraphManager {
|
|
|
167
166
|
);
|
|
168
167
|
|
|
169
168
|
// TODO: Add instance profile with instance role
|
|
170
|
-
let
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
user_data: user_data.clone(),
|
|
176
|
-
})));
|
|
177
|
-
|
|
178
|
-
instances.push(instance_node);
|
|
179
|
-
}
|
|
169
|
+
let vm = deps.add_node(SpecNode::Resource(ResourceSpecType::Vm(VmSpec {
|
|
170
|
+
instance_type: instance_type.clone(),
|
|
171
|
+
ami: String::from("ami-04dd23e62ed049936"),
|
|
172
|
+
user_data,
|
|
173
|
+
})));
|
|
180
174
|
|
|
181
175
|
// Order of the edges matters in this implementation
|
|
182
176
|
// Nodes within the same parent are traversed from
|
|
@@ -192,13 +186,12 @@ impl GraphManager {
|
|
|
192
186
|
(igw_1, route_table_1, String::new()), // 7
|
|
193
187
|
(route_table_1, subnet_1, String::new()), // 8
|
|
194
188
|
(instance_role_1, instance_profile_1, String::new()), // 9
|
|
189
|
+
// VM
|
|
190
|
+
(subnet_1, vm, String::new()),
|
|
191
|
+
(instance_profile_1, vm, String::new()),
|
|
192
|
+
(security_group_1, vm, String::new()),
|
|
193
|
+
(ecr_1, vm, String::new()),
|
|
195
194
|
];
|
|
196
|
-
for instance in &instances {
|
|
197
|
-
edges.push((subnet_1, *instance, String::new()));
|
|
198
|
-
edges.push((instance_profile_1, *instance, String::new()));
|
|
199
|
-
edges.push((security_group_1, *instance, String::new()));
|
|
200
|
-
edges.push((ecr_1, *instance, String::new()));
|
|
201
|
-
}
|
|
202
195
|
|
|
203
196
|
if let Some(domain_name) = domain_name {
|
|
204
197
|
let hosted_zone = deps.add_node(SpecNode::Resource(ResourceSpecType::HostedZone(
|
|
@@ -211,17 +204,15 @@ impl GraphManager {
|
|
|
211
204
|
// Insert at the first place to deploy it after all other root's children
|
|
212
205
|
edges.insert(0, (root, hosted_zone, String::new()));
|
|
213
206
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
)));
|
|
207
|
+
let dns_record = deps.add_node(SpecNode::Resource(ResourceSpecType::DnsRecord(
|
|
208
|
+
DnsRecordSpec {
|
|
209
|
+
record_type: types::RecordType::A,
|
|
210
|
+
ttl: Some(3600),
|
|
211
|
+
},
|
|
212
|
+
)));
|
|
221
213
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
}
|
|
214
|
+
edges.push((vm, dns_record, String::new()));
|
|
215
|
+
edges.push((hosted_zone, dns_record, String::new()));
|
|
225
216
|
}
|
|
226
217
|
|
|
227
218
|
deps.extend_with_edges(&edges);
|
|
@@ -236,14 +227,14 @@ impl GraphManager {
|
|
|
236
227
|
pub async fn deploy(
|
|
237
228
|
&self,
|
|
238
229
|
graph: &Graph<SpecNode, String>,
|
|
239
|
-
) -> Result<(Graph<Node, String>,
|
|
230
|
+
) -> Result<(Graph<Node, String>, Option<Vm>, Option<Ecr>), Box<dyn std::error::Error>> {
|
|
240
231
|
let mut resource_graph = Graph::<Node, String>::new();
|
|
241
232
|
let mut edges = vec![];
|
|
242
233
|
|
|
243
234
|
let mut parents: HashMap<NodeIndex, Vec<NodeIndex>> = HashMap::new();
|
|
244
235
|
|
|
245
236
|
let mut ecr: Option<Ecr> = None;
|
|
246
|
-
let mut
|
|
237
|
+
let mut vm: Option<Vm> = None;
|
|
247
238
|
|
|
248
239
|
let result = kahn_traverse(graph)?;
|
|
249
240
|
|
|
@@ -381,7 +372,7 @@ impl GraphManager {
|
|
|
381
372
|
|
|
382
373
|
match output_vm {
|
|
383
374
|
Ok(output_vm) => {
|
|
384
|
-
|
|
375
|
+
vm = Some(output_vm.clone());
|
|
385
376
|
|
|
386
377
|
Ok(Node::Resource(ResourceType::Vm(output_vm)))
|
|
387
378
|
}
|
|
@@ -419,7 +410,7 @@ impl GraphManager {
|
|
|
419
410
|
|
|
420
411
|
log::info!("Created graph {}", Dot::new(&resource_graph));
|
|
421
412
|
|
|
422
|
-
Ok((resource_graph,
|
|
413
|
+
Ok((resource_graph, vm, ecr))
|
|
423
414
|
}
|
|
424
415
|
|
|
425
416
|
/// Destroys resource graph
|
|
@@ -608,121 +599,43 @@ mod tests {
|
|
|
608
599
|
#[test]
|
|
609
600
|
fn test_get_spec_graph_with_one_instance_no_domain() {
|
|
610
601
|
// Arrange
|
|
611
|
-
let
|
|
612
|
-
let instance_type = InstanceType::T2Micro;
|
|
613
|
-
let domain_name = None;
|
|
614
|
-
|
|
615
|
-
// Act
|
|
616
|
-
let graph = GraphManager::get_spec_graph(number_of_instances, &instance_type, domain_name);
|
|
617
|
-
|
|
618
|
-
// Assert
|
|
619
|
-
let number_of_nodes = 9 + number_of_instances;
|
|
620
|
-
let number_of_edges = 10 + 4 * number_of_instances;
|
|
621
|
-
assert_eq!(graph.node_count(), number_of_nodes as usize);
|
|
622
|
-
assert_eq!(graph.edge_count(), number_of_edges as usize);
|
|
623
|
-
|
|
624
|
-
let vm_nodes_count = graph
|
|
625
|
-
.raw_nodes()
|
|
626
|
-
.iter()
|
|
627
|
-
.filter(|node| matches!(&node.weight, SpecNode::Resource(ResourceSpecType::Vm(_))))
|
|
628
|
-
.count();
|
|
629
|
-
assert_eq!(vm_nodes_count, number_of_instances as usize);
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
#[test]
|
|
633
|
-
fn test_get_spec_graph_with_multiple_instances_no_domain() {
|
|
634
|
-
// Arrange
|
|
635
|
-
let number_of_instances = 3;
|
|
636
|
-
let instance_type = InstanceType::T2Micro;
|
|
602
|
+
let instance_type = InstanceType::T3Micro;
|
|
637
603
|
let domain_name = None;
|
|
638
604
|
|
|
639
605
|
// Act
|
|
640
|
-
let graph = GraphManager::get_spec_graph(
|
|
606
|
+
let graph = GraphManager::get_spec_graph(&instance_type, domain_name);
|
|
641
607
|
|
|
642
608
|
// Assert
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
assert_eq!(graph.node_count(), number_of_nodes as usize);
|
|
646
|
-
assert_eq!(graph.edge_count(), number_of_edges as usize);
|
|
609
|
+
assert_eq!(graph.node_count(), 10);
|
|
610
|
+
assert_eq!(graph.edge_count(), 10 + 4);
|
|
647
611
|
|
|
648
612
|
let vm_nodes_count = graph
|
|
649
613
|
.raw_nodes()
|
|
650
614
|
.iter()
|
|
651
615
|
.filter(|node| matches!(&node.weight, SpecNode::Resource(ResourceSpecType::Vm(_))))
|
|
652
616
|
.count();
|
|
653
|
-
assert_eq!(vm_nodes_count,
|
|
617
|
+
assert_eq!(vm_nodes_count, 1);
|
|
654
618
|
}
|
|
655
619
|
|
|
656
620
|
#[test]
|
|
657
621
|
fn test_get_spec_graph_with_one_instance_and_domain() {
|
|
658
622
|
// Arrange
|
|
659
|
-
let
|
|
660
|
-
let instance_type = InstanceType::T2Micro;
|
|
661
|
-
let domain_name = Some(String::from("example.com"));
|
|
662
|
-
|
|
663
|
-
// Act
|
|
664
|
-
let graph = GraphManager::get_spec_graph(number_of_instances, &instance_type, domain_name);
|
|
665
|
-
|
|
666
|
-
// Assert
|
|
667
|
-
let number_of_nodes = 10 + 2 * number_of_instances;
|
|
668
|
-
let number_of_edges = 11 + 6 * number_of_instances;
|
|
669
|
-
assert_eq!(graph.node_count(), number_of_nodes as usize);
|
|
670
|
-
assert_eq!(graph.edge_count(), number_of_edges as usize);
|
|
671
|
-
|
|
672
|
-
let vm_nodes_count = graph
|
|
673
|
-
.raw_nodes()
|
|
674
|
-
.iter()
|
|
675
|
-
.filter(|node| matches!(&node.weight, SpecNode::Resource(ResourceSpecType::Vm(_))))
|
|
676
|
-
.count();
|
|
677
|
-
assert_eq!(vm_nodes_count, number_of_instances as usize);
|
|
678
|
-
|
|
679
|
-
let hosted_zone_nodes_count = graph
|
|
680
|
-
.raw_nodes()
|
|
681
|
-
.iter()
|
|
682
|
-
.filter(|node| {
|
|
683
|
-
matches!(
|
|
684
|
-
&node.weight,
|
|
685
|
-
SpecNode::Resource(ResourceSpecType::HostedZone(_))
|
|
686
|
-
)
|
|
687
|
-
})
|
|
688
|
-
.count();
|
|
689
|
-
assert_eq!(hosted_zone_nodes_count, 1);
|
|
690
|
-
|
|
691
|
-
let dns_record_nodes_count = graph
|
|
692
|
-
.raw_nodes()
|
|
693
|
-
.iter()
|
|
694
|
-
.filter(|node| {
|
|
695
|
-
matches!(
|
|
696
|
-
&node.weight,
|
|
697
|
-
SpecNode::Resource(ResourceSpecType::DnsRecord(_))
|
|
698
|
-
)
|
|
699
|
-
})
|
|
700
|
-
.count();
|
|
701
|
-
assert_eq!(dns_record_nodes_count, number_of_instances as usize);
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
#[test]
|
|
705
|
-
fn test_get_spec_graph_with_multiple_instances_and_domain() {
|
|
706
|
-
// Arrange
|
|
707
|
-
let number_of_instances = 3;
|
|
708
|
-
let instance_type = InstanceType::T2Micro;
|
|
623
|
+
let instance_type = InstanceType::T3Micro;
|
|
709
624
|
let domain_name = Some(String::from("example.com"));
|
|
710
625
|
|
|
711
626
|
// Act
|
|
712
|
-
let graph = GraphManager::get_spec_graph(
|
|
627
|
+
let graph = GraphManager::get_spec_graph(&instance_type, domain_name);
|
|
713
628
|
|
|
714
629
|
// Assert
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
assert_eq!(graph.node_count(), number_of_nodes as usize);
|
|
718
|
-
assert_eq!(graph.edge_count(), number_of_edges as usize);
|
|
630
|
+
assert_eq!(graph.node_count(), 10 + 2);
|
|
631
|
+
assert_eq!(graph.edge_count(), 11 + 6);
|
|
719
632
|
|
|
720
633
|
let vm_nodes_count = graph
|
|
721
634
|
.raw_nodes()
|
|
722
635
|
.iter()
|
|
723
636
|
.filter(|node| matches!(&node.weight, SpecNode::Resource(ResourceSpecType::Vm(_))))
|
|
724
637
|
.count();
|
|
725
|
-
assert_eq!(vm_nodes_count,
|
|
638
|
+
assert_eq!(vm_nodes_count, 1);
|
|
726
639
|
|
|
727
640
|
let hosted_zone_nodes_count = graph
|
|
728
641
|
.raw_nodes()
|
|
@@ -746,18 +659,16 @@ mod tests {
|
|
|
746
659
|
)
|
|
747
660
|
})
|
|
748
661
|
.count();
|
|
749
|
-
assert_eq!(dns_record_nodes_count,
|
|
662
|
+
assert_eq!(dns_record_nodes_count, 1);
|
|
750
663
|
}
|
|
751
664
|
|
|
752
665
|
#[tokio::test]
|
|
753
666
|
async fn test_deploy_with_one_instance_no_domain() {
|
|
754
667
|
// Arrange
|
|
755
|
-
let
|
|
756
|
-
let instance_type = InstanceType::T2Micro;
|
|
668
|
+
let instance_type = InstanceType::T3Micro;
|
|
757
669
|
let domain_name = None;
|
|
758
670
|
|
|
759
|
-
let spec_graph =
|
|
760
|
-
GraphManager::get_spec_graph(number_of_instances, &instance_type, domain_name);
|
|
671
|
+
let spec_graph = GraphManager::get_spec_graph(&instance_type, domain_name);
|
|
761
672
|
|
|
762
673
|
let mut ec2_client_mock = client::Ec2::default();
|
|
763
674
|
let mut iam_client_mock = client::IAM::default();
|
|
@@ -909,7 +820,7 @@ mod tests {
|
|
|
909
820
|
);
|
|
910
821
|
|
|
911
822
|
// Act
|
|
912
|
-
let (resource_graph,
|
|
823
|
+
let (resource_graph, vm, ecr) = graph_manager
|
|
913
824
|
.deploy(&spec_graph)
|
|
914
825
|
.await
|
|
915
826
|
.expect("Failed to deploy");
|
|
@@ -919,12 +830,12 @@ mod tests {
|
|
|
919
830
|
assert_eq!(resource_graph.edge_count(), 14);
|
|
920
831
|
|
|
921
832
|
assert_eq!(
|
|
922
|
-
|
|
923
|
-
|
|
833
|
+
vm,
|
|
834
|
+
Some(Vm {
|
|
924
835
|
id: String::from("vm-id-1"),
|
|
925
836
|
public_ip: String::from("1.2.3.4"),
|
|
926
837
|
ami: String::from("ami-04dd23e62ed049936"),
|
|
927
|
-
instance_type: InstanceType::
|
|
838
|
+
instance_type: InstanceType::T3Micro,
|
|
928
839
|
user_data: String::from(
|
|
929
840
|
r#"#!/bin/bash
|
|
930
841
|
set -e
|
|
@@ -942,7 +853,7 @@ mod tests {
|
|
|
942
853
|
|
|
943
854
|
aws ecr get-login-password --region us-west-2 | podman login --username AWS --password-stdin ecr-uri-1"#
|
|
944
855
|
)
|
|
945
|
-
}
|
|
856
|
+
})
|
|
946
857
|
);
|
|
947
858
|
|
|
948
859
|
assert_eq!(
|
|
@@ -973,7 +884,7 @@ aws ecr get-login-password --region us-west-2 | podman login --username AWS --pa
|
|
|
973
884
|
);
|
|
974
885
|
|
|
975
886
|
// Act
|
|
976
|
-
let (resource_graph,
|
|
887
|
+
let (resource_graph, vm, ecr) = graph_manager
|
|
977
888
|
.deploy(&spec_graph)
|
|
978
889
|
.await
|
|
979
890
|
.expect("Failed to deploy");
|
|
@@ -981,7 +892,7 @@ aws ecr get-login-password --region us-west-2 | podman login --username AWS --pa
|
|
|
981
892
|
// Assert
|
|
982
893
|
assert_eq!(resource_graph.node_count(), 0);
|
|
983
894
|
assert_eq!(resource_graph.edge_count(), 0);
|
|
984
|
-
assert!(
|
|
895
|
+
assert!(vm.is_none());
|
|
985
896
|
assert!(ecr.is_none());
|
|
986
897
|
}
|
|
987
898
|
|
|
@@ -1036,7 +947,7 @@ aws ecr get-login-password --region us-west-2 | podman login --username AWS --pa
|
|
|
1036
947
|
);
|
|
1037
948
|
|
|
1038
949
|
// Act
|
|
1039
|
-
let (resource_graph,
|
|
950
|
+
let (resource_graph, vm, ecr) = graph_manager
|
|
1040
951
|
.deploy(&spec_graph)
|
|
1041
952
|
.await
|
|
1042
953
|
.expect("Failed to deploy");
|
|
@@ -1045,7 +956,7 @@ aws ecr get-login-password --region us-west-2 | podman login --username AWS --pa
|
|
|
1045
956
|
// 1 root + VPC
|
|
1046
957
|
assert_eq!(resource_graph.node_count(), 2);
|
|
1047
958
|
assert_eq!(resource_graph.edge_count(), 1);
|
|
1048
|
-
assert!(
|
|
959
|
+
assert!(vm.is_none());
|
|
1049
960
|
assert!(ecr.is_none());
|
|
1050
961
|
|
|
1051
962
|
let vpc_node_exists = resource_graph
|
|
@@ -1339,7 +1250,7 @@ aws ecr get-login-password --region us-west-2 | podman login --username AWS --pa
|
|
|
1339
1250
|
id: "vm-id-1".to_string(),
|
|
1340
1251
|
public_ip: "1.2.3.4".to_string(),
|
|
1341
1252
|
ami: "ami-04dd23e62ed049936".to_string(),
|
|
1342
|
-
instance_type: InstanceType::
|
|
1253
|
+
instance_type: InstanceType::T3Micro,
|
|
1343
1254
|
user_data: String::new(), // Not used in destroy
|
|
1344
1255
|
})));
|
|
1345
1256
|
|
|
@@ -2107,7 +2107,7 @@ mod tests {
|
|
|
2107
2107
|
let vm = Vm {
|
|
2108
2108
|
id: String::from("vm-id"),
|
|
2109
2109
|
public_ip: String::from("1.2.3.4"),
|
|
2110
|
-
instance_type: types::InstanceType::
|
|
2110
|
+
instance_type: types::InstanceType::T3Micro,
|
|
2111
2111
|
ami: String::from("ami-123"),
|
|
2112
2112
|
user_data: String::new(),
|
|
2113
2113
|
};
|
|
@@ -2148,7 +2148,7 @@ mod tests {
|
|
|
2148
2148
|
let vm = Vm {
|
|
2149
2149
|
id: String::from("vm-id"),
|
|
2150
2150
|
public_ip: String::from("1.2.3.4"),
|
|
2151
|
-
instance_type: types::InstanceType::
|
|
2151
|
+
instance_type: types::InstanceType::T3Micro,
|
|
2152
2152
|
ami: String::from("ami-123"),
|
|
2153
2153
|
user_data: String::new(),
|
|
2154
2154
|
};
|
|
@@ -2222,7 +2222,7 @@ mod tests {
|
|
|
2222
2222
|
let vm = Vm {
|
|
2223
2223
|
id: String::from("vm-id"),
|
|
2224
2224
|
public_ip: String::from("1.2.3.4"),
|
|
2225
|
-
instance_type: types::InstanceType::
|
|
2225
|
+
instance_type: types::InstanceType::T3Micro,
|
|
2226
2226
|
ami: String::from("ami-123"),
|
|
2227
2227
|
user_data: String::new(),
|
|
2228
2228
|
};
|
|
@@ -2719,7 +2719,7 @@ mod tests {
|
|
|
2719
2719
|
};
|
|
2720
2720
|
|
|
2721
2721
|
let vm_spec = VmSpec {
|
|
2722
|
-
instance_type: types::InstanceType::
|
|
2722
|
+
instance_type: types::InstanceType::T3Micro,
|
|
2723
2723
|
ami: String::from("ami-123"),
|
|
2724
2724
|
user_data: String::from("user-data"),
|
|
2725
2725
|
};
|
|
@@ -2761,7 +2761,7 @@ mod tests {
|
|
|
2761
2761
|
Vm {
|
|
2762
2762
|
id: String::from("vm-id"),
|
|
2763
2763
|
public_ip: String::from("1.2.3.4"),
|
|
2764
|
-
instance_type: types::InstanceType::
|
|
2764
|
+
instance_type: types::InstanceType::T3Micro,
|
|
2765
2765
|
ami: String::from("ami-123"),
|
|
2766
2766
|
user_data: String::from(
|
|
2767
2767
|
"user-data\naws ecr get-login-password --region us-west-2 | podman login --username AWS --password-stdin dkr.ecr.region.amazonaws.com",
|
|
@@ -2778,7 +2778,7 @@ mod tests {
|
|
|
2778
2778
|
client: &ec2_client_mock,
|
|
2779
2779
|
};
|
|
2780
2780
|
let vm_spec = VmSpec {
|
|
2781
|
-
instance_type: types::InstanceType::
|
|
2781
|
+
instance_type: types::InstanceType::T3Micro,
|
|
2782
2782
|
ami: String::from("ami-123"),
|
|
2783
2783
|
user_data: String::from("user-data"),
|
|
2784
2784
|
};
|
|
@@ -2820,7 +2820,7 @@ mod tests {
|
|
|
2820
2820
|
client: &ec2_client_mock,
|
|
2821
2821
|
};
|
|
2822
2822
|
let vm_spec = VmSpec {
|
|
2823
|
-
instance_type: types::InstanceType::
|
|
2823
|
+
instance_type: types::InstanceType::T3Micro,
|
|
2824
2824
|
ami: String::from("ami-123"),
|
|
2825
2825
|
user_data: String::from("user-data"),
|
|
2826
2826
|
};
|
|
@@ -2863,7 +2863,7 @@ mod tests {
|
|
|
2863
2863
|
client: &ec2_client_mock,
|
|
2864
2864
|
};
|
|
2865
2865
|
let vm_spec = VmSpec {
|
|
2866
|
-
instance_type: types::InstanceType::
|
|
2866
|
+
instance_type: types::InstanceType::T3Micro,
|
|
2867
2867
|
ami: String::from("ami-123"),
|
|
2868
2868
|
user_data: String::from("user-data"),
|
|
2869
2869
|
};
|
|
@@ -2908,7 +2908,7 @@ mod tests {
|
|
|
2908
2908
|
client: &ec2_client_mock,
|
|
2909
2909
|
};
|
|
2910
2910
|
let vm_spec = VmSpec {
|
|
2911
|
-
instance_type: types::InstanceType::
|
|
2911
|
+
instance_type: types::InstanceType::T3Micro,
|
|
2912
2912
|
ami: String::from("ami-123"),
|
|
2913
2913
|
user_data: String::from("user-data"),
|
|
2914
2914
|
};
|
|
@@ -2956,7 +2956,7 @@ mod tests {
|
|
|
2956
2956
|
};
|
|
2957
2957
|
|
|
2958
2958
|
let vm_spec = VmSpec {
|
|
2959
|
-
instance_type: types::InstanceType::
|
|
2959
|
+
instance_type: types::InstanceType::T3Micro,
|
|
2960
2960
|
ami: String::from("ami-123"),
|
|
2961
2961
|
user_data: String::from("user-data"),
|
|
2962
2962
|
};
|
|
@@ -3019,7 +3019,7 @@ mod tests {
|
|
|
3019
3019
|
let vm = Vm {
|
|
3020
3020
|
id: String::from("vm-id"),
|
|
3021
3021
|
public_ip: String::from("1.2.3.4"),
|
|
3022
|
-
instance_type: types::InstanceType::
|
|
3022
|
+
instance_type: types::InstanceType::T3Micro,
|
|
3023
3023
|
ami: String::from("ami-123"),
|
|
3024
3024
|
user_data: String::from("user-data"),
|
|
3025
3025
|
};
|
|
@@ -3047,7 +3047,7 @@ mod tests {
|
|
|
3047
3047
|
let vm = Vm {
|
|
3048
3048
|
id: String::from("vm-id"),
|
|
3049
3049
|
public_ip: String::from("1.2.3.4"),
|
|
3050
|
-
instance_type: types::InstanceType::
|
|
3050
|
+
instance_type: types::InstanceType::T3Micro,
|
|
3051
3051
|
ami: String::from("ami-123"),
|
|
3052
3052
|
user_data: String::from("user-data"),
|
|
3053
3053
|
};
|
{opencloudtool-0.6.1/crates/oct-orchestrator → opencloudtool-0.7.0/crates/oct-ctl-sdk}/README.md
RENAMED
|
@@ -230,3 +230,7 @@ Total: $92 per month
|
|
|
230
230
|
- 1 EC2 [t4g.medium](https://aws.amazon.com/ec2/pricing/on-demand/) instance ($0.0336 per hour): $25.5 per month
|
|
231
231
|
|
|
232
232
|
Total: $25.5 per month
|
|
233
|
+
|
|
234
|
+
## Repo stats
|
|
235
|
+
|
|
236
|
+

|
{opencloudtool-0.6.1/crates/oct-ctl-sdk → opencloudtool-0.7.0/crates/oct-orchestrator}/README.md
RENAMED
|
@@ -230,3 +230,7 @@ Total: $92 per month
|
|
|
230
230
|
- 1 EC2 [t4g.medium](https://aws.amazon.com/ec2/pricing/on-demand/) instance ($0.0336 per hour): $25.5 per month
|
|
231
231
|
|
|
232
232
|
Total: $25.5 per month
|
|
233
|
+
|
|
234
|
+
## Repo stats
|
|
235
|
+
|
|
236
|
+

|
|
@@ -16,8 +16,6 @@ mod user_state;
|
|
|
16
16
|
pub struct OrchestratorWithGraph;
|
|
17
17
|
|
|
18
18
|
impl OrchestratorWithGraph {
|
|
19
|
-
const INSTANCE_TYPE: InstanceType = InstanceType::T2Micro;
|
|
20
|
-
|
|
21
19
|
pub async fn deploy(&self) -> Result<(), Box<dyn std::error::Error>> {
|
|
22
20
|
let mut config = config::Config::new(None)?;
|
|
23
21
|
|
|
@@ -33,34 +31,26 @@ impl OrchestratorWithGraph {
|
|
|
33
31
|
backend::get_state_backend::<user_state::UserState>(&config.project.user_state_backend);
|
|
34
32
|
let (mut user_state, _loaded) = user_state_backend.load().await?;
|
|
35
33
|
|
|
36
|
-
let
|
|
37
|
-
get_number_of_needed_instances(&services_graph, &Self::INSTANCE_TYPE)?;
|
|
34
|
+
let instance_type = get_instance_type(&services_graph)?;
|
|
38
35
|
|
|
39
|
-
log::info!("
|
|
36
|
+
log::info!("Instance to be created: {instance_type:?}");
|
|
40
37
|
|
|
41
38
|
let spec_graph = infra::graph::GraphManager::get_spec_graph(
|
|
42
|
-
|
|
43
|
-
&Self::INSTANCE_TYPE,
|
|
39
|
+
&instance_type,
|
|
44
40
|
config.project.domain.clone(),
|
|
45
41
|
);
|
|
46
42
|
|
|
47
43
|
let infra_graph_manager = infra::graph::GraphManager::new().await;
|
|
48
|
-
let (resource_graph,
|
|
44
|
+
let (resource_graph, vm, ecr) = infra_graph_manager.deploy(&spec_graph).await?;
|
|
49
45
|
|
|
50
46
|
let state = infra::state::State::from_graph(&resource_graph);
|
|
51
47
|
let () = infra_state_backend.save(&state).await?;
|
|
52
48
|
|
|
53
|
-
|
|
54
|
-
// Add missing instances to state
|
|
55
|
-
// TODO: Handle removing instances
|
|
56
|
-
if user_state.instances.contains_key(&vm.public_ip) {
|
|
57
|
-
continue;
|
|
58
|
-
}
|
|
59
|
-
|
|
49
|
+
if let Some(vm) = vm {
|
|
60
50
|
let instance_info = vm.instance_type.get_info();
|
|
61
51
|
|
|
62
52
|
user_state.instances.insert(
|
|
63
|
-
vm.public_ip
|
|
53
|
+
vm.public_ip,
|
|
64
54
|
user_state::Instance {
|
|
65
55
|
cpus: instance_info.cpus,
|
|
66
56
|
memory: instance_info.memory,
|
|
@@ -141,13 +131,10 @@ impl OrchestratorWithGraph {
|
|
|
141
131
|
}
|
|
142
132
|
}
|
|
143
133
|
|
|
144
|
-
///
|
|
145
|
-
|
|
146
|
-
/// a single EC2 instance capacity
|
|
147
|
-
fn get_number_of_needed_instances(
|
|
134
|
+
/// Tries to find an instance type which can fit all user-requested services
|
|
135
|
+
fn get_instance_type(
|
|
148
136
|
services_graph: &Graph<config::Node, String>,
|
|
149
|
-
|
|
150
|
-
) -> Result<u32, Box<dyn std::error::Error>> {
|
|
137
|
+
) -> Result<InstanceType, Box<dyn std::error::Error>> {
|
|
151
138
|
let sorted_graph = infra::graph::kahn_traverse(services_graph)?;
|
|
152
139
|
|
|
153
140
|
let total_services_cpus = sorted_graph
|
|
@@ -174,15 +161,12 @@ fn get_number_of_needed_instances(
|
|
|
174
161
|
.map(|service| service.memory)
|
|
175
162
|
.sum::<u64>();
|
|
176
163
|
|
|
177
|
-
let
|
|
164
|
+
let instance_type = InstanceType::from_resources(total_services_cpus, total_services_memory);
|
|
178
165
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
needed_instances_count_by_cpus,
|
|
184
|
-
u32::try_from(needed_instances_count_by_memory).unwrap_or_default(),
|
|
185
|
-
))
|
|
166
|
+
match instance_type {
|
|
167
|
+
Some(instance_type) => Ok(instance_type),
|
|
168
|
+
None => Err("Failed to get instance type to fit all services".into()),
|
|
169
|
+
}
|
|
186
170
|
}
|
|
187
171
|
|
|
188
172
|
/// Deploys user services
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|