gcloud_utils/sql/
process.rs

1use tokio::process::Command;
2use console::style;
3use std::io;
4use regex::Regex;
5use std::str;
6
7fn regex(re_str: &str) -> Regex {
8  Regex::new(re_str).unwrap()
9}
10
11pub async fn process_create_sql(project_id: &str, service_name: &str, region: &str) {
12  println!(
13    "📝 {}",
14    style("Please input your DB Root Password:").white().bold()
15  );
16  let mut db_password = String::new();
17  io::stdin()
18    .read_line(&mut db_password)
19    .expect("Failed to read line");
20  let db_password: String = db_password
21    .trim()
22    .parse()
23    .expect("Please input DB Root Password:");
24  let zone = String::from(region) + "-b";
25  println!(
26    "⏰ {}",
27    style("Creating Cloud SQL ...\nThis process takes 5 to 10 min.").white().bold()
28  );
29  let instance_name = String::from(service_name) + "-db";
30  let db_version = String::from("--database-version=POSTGRES_14");
31  let output = Command::new("gcloud")
32    .args(&[
33      "sql",
34      "instances",
35      "create",
36      &instance_name,
37      &db_version,
38      "--cpu=1",
39      "--memory=4096MB",
40      "--zone",
41      &zone,
42      "--root-password",
43      &db_password,
44      "--database-flags",
45      "cloudsql.iam_authentication=on",
46      "--project",
47      project_id
48    ])
49    .output()
50    .await;
51  match &output {
52    Ok(val) => {
53      let err = str::from_utf8(&val.stderr);
54      let rt = regex("ERROR:");
55      match rt.is_match(err.unwrap()) {
56        true => {
57            panic!("{:?}", err.unwrap())
58        }
59        false => {
60          println!(
61              "✅ {}",
62              style("Successfully created Cloud SQL!").white().bold()
63          );
64        }
65      }
66    },
67    Err(err) => println!("error = {:?}", err)
68  }
69}
70
71pub async fn process_create_ip_range(project_id: &str, service_name: &str) {
72  println!(
73    "⏰ {}",
74    style("Creating IP range ...\nThis process takes 5 to 10 min.").white().bold()
75  );
76  let ip_range_name = String::from(service_name) + "-ip-range";
77  let network = String::from("--network=") + service_name;
78  let output = Command::new("gcloud")
79    .args(&[
80      "compute",
81      "addresses",
82      "create",
83      &ip_range_name,
84      "--global",
85      "--purpose=VPC_PEERING",
86      "--prefix-length=16",
87      "--description='peering range for Epics'",
88      &network,
89      "--project",
90      project_id
91    ])
92    .output()
93    .await;
94  match &output {
95    Ok(val) => {
96      let err = str::from_utf8(&val.stderr);
97      let rt = regex("ERROR:");
98      match rt.is_match(err.unwrap()) {
99        true => {
100            panic!("{:?}", err.unwrap())
101        }
102        false => {
103          println!(
104              "✅ {}",
105              style("Successfully created IP range!").white().bold()
106          );
107        }
108      }
109    },
110    Err(err) => println!("error = {:?}", err)
111  }
112}
113
114pub async fn process_connect_vpc_connector(project_id: &str, service_name: &str) {
115  println!(
116    "⏰ {}",
117    style("Connecting to VPC Connector ...\nThis process takes 5 to 10 min.").white().bold()
118  );
119  let ip_range_name = String::from(service_name) + "-ip-range";
120  let network = String::from("--network=") + service_name;
121  let output = Command::new("gcloud")
122    .args(&[
123      "services",
124      "vpc-peerings",
125      "connect",
126      "--service=servicenetworking.googleapis.com",
127      "--ranges",
128      &ip_range_name,
129      &network,
130      "--project",
131      project_id
132    ])
133    .output()
134    .await;
135  match &output {
136    Ok(val) => {
137      let err = str::from_utf8(&val.stderr);
138      let rt = regex("ERROR:");
139      match rt.is_match(err.unwrap()) {
140        true => {
141            panic!("{:?}", err.unwrap())
142        }
143        false => {
144          println!(
145              "✅ {}",
146              style("Successfully connected to VPC!").white().bold()
147          );
148        }
149      }
150    },
151    Err(err) => println!("error = {:?}", err)
152  }
153}
154
155pub async fn process_assign_network(project_id: &str, service_name: &str) {
156  println!(
157    "⏰ {}",
158    style("Assign network ...\nThis process takes 5 to 10 min.").white().bold()
159  );
160  let instance_name = String::from(service_name) + "-db";
161  let network = String::from("--network=") + service_name;
162  let output = Command::new("gcloud")
163    .args(&[
164      "beta",
165      "sql",
166      "instances",
167      "patch",
168      &instance_name,
169      &network,
170      "--project",
171      project_id
172    ])
173    .output()
174    .await;
175  match &output {
176    Ok(val) => {
177      let err = str::from_utf8(&val.stderr);
178      let rt = regex("ERROR:");
179      match rt.is_match(err.unwrap()) {
180        true => {
181            panic!("{:?}", err.unwrap())
182        }
183        false => {
184          println!(
185              "✅ {}",
186              style("Successfully setup your database!").white().bold()
187          );
188        }
189      }
190    },
191    Err(err) => println!("error = {:?}", err)
192  }
193}
194
195async fn region_to_timezone(region: &str) -> &str {
196  let asia = regex("asia");
197  let eu = regex("europe");
198  let zone = if asia.is_match(region)  {
199    "Asia/Tokyo"
200  } else if eu.is_match(region) {
201    "Europe/Amsterdam"
202  } else {
203    "America/Los_Angeles"
204  };
205  zone
206}