diff --git a/.machine_name.txt b/.machine_name.txt index 1235c24..cdb6f3b 100644 --- a/.machine_name.txt +++ b/.machine_name.txt @@ -1 +1 @@ -EC2-geotail-154000 \ No newline at end of file +EC2-geotail-155163 \ No newline at end of file diff --git a/a.txt b/a.txt new file mode 100644 index 0000000..54d8ed3 --- /dev/null +++ b/a.txt @@ -0,0 +1 @@ +The servers IP address is ??? diff --git a/funawskeyb1021204.pem b/funawskeyb1021204.pem new file mode 100644 index 0000000..ab4bd23 --- /dev/null +++ b/funawskeyb1021204.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAuJrIDJmxuEH8W4p5sn+FK4Mt3bDfe73QkDSZ5FPbw0DICdBy ++it9sbaerWFjKmdEKnBAxo5OJhlNNn2XJm4nP2b3cMpc24wcgQnJnxqizt1gdTsX +prUP8Vh3MC+Emf+T7eGMBXsRCNHtAdOIN14uEWUu9tkRaR6o2Z7C5WZ+6Mb+ky98 +eEY3pr8jOznFo55LmlKUFfifDBDWzOaH1YGtjOoj+HeVspZGwB/rfWWrLuSKm3jc +/8pt8WLhwE437bhi2dQ1cWiWWxveoZOvR3quOiNON4AzVKLwt58TZMRSNpcPNXUN +KFWEEhDVJo4+4+DXQDVCvFjv5lJE4cXARrnvLwIDAQABAoIBAQCrsIjN70OysuwZ +1zhIIwGf7mkB/jZbx7Xp6IIYMUX62o0xU4Ub1scYOVhquGCaV2C2d6BHCqL0HCQL +wdKKE3i9Ju6LICospqr7+DZkm0lAS/QiE8tzaIJjXHu9fPQ+pczXOSYZEtRM97EO +OcY+eIEv/IMpYcknkzRG8bkh0anGo3RO6bZIA1LjwS0OqBVejimK/qegXitOJ3ml +XPDAnL/X9VqmEU7zLBPY2CqPlwBnV2mEoAN1fyL8EYrgx8EQ5o2KdmhPi7dDIaAV +VXR4SLFRRnZam4hs7FsYRHKn7J3mdJu1diFtHXsWGO5FNuSnopFAdarkGCNUs0Pt +xjFaXFvBAoGBAPpBHv9GYdL49zQOgHLsVezYuKJYaq3yQwgt4EPsPW+facBgdiAm +b4YhIc8nC2AdickW65MTsD8JCv142YoCXF9Wjv2ktpiRhkzfMmOR25OJONDDhQaB +XgrF86oIlN8f9CoGvW7F1DtqM/HBFVF4WgXJNkKwxgjOx3W5D0jT2mP1AoGBALzX +zTMZZA/XmJ8sXcd7fjsaAK7HgmbIv6DwLMduxUxjwJ8nDwvSh/ZCiqVkwrkDv0i9 +3hA1I2M+Rg3vAkvnoaPQqy7WQSIdNiGbLdAJXXnwfQ5D9WIUZl0r98XGokVHR2SN +XH/lULJyn4yumSz/cCJlIBUSUJQLp1VJZZg04/QTAoGBAPB3rs9g1BMjhHaTEL5d +dlt2DESDbU7kIaE0Y/EgihA+QCHJDvjptfRO1ev1+qpK9+EwkwDqxEpt6A+UFoTU +q+o4hIIZyhNkkoY/Wm3u8+0ayGth1OthV/pGKFNUl6inTbksbM6KbdsBvBQrks6M +NQSmSetfbYt9FpB6WMOEPrAZAoGABQFPPgB5R3Y2ZFmfrq7WPKjGxdsh2KmPcquK +9Eo6TnkCXPWDD5Qn6F4BILsX8iFoS3xEy3ctFe9LmgjwraRZA2d/cgFZvpa5nZBo +WXA2GwpFtkAU2+GgiO2mZoaKPH3UJZUdk4I3blNdaTQjeS7YAQFfJU/T9OiOKdOF +LtCQDiMCgYBJAajrQsBuKE4uHQmRkvXMSEo7TmCuQmPCSwmSfVW1cJNUj2Idl5re +VGGZPvbY27ZSMJMJ3pNqj6HtMFWBAPCwj96VtiK3gG18NDSw1TgTdK8Vf97sM7YD +xpj7Qp2ffZvzJvTlwjXtAEUsZQ+WZyiz4t0lv37n93N6RfJvASt8/Q== +-----END RSA PRIVATE KEY----- \ No newline at end of file diff --git a/internal/provider/VM_resource.go b/internal/provider/VM_resource.go index bcc910b..538efea 100644 --- a/internal/provider/VM_resource.go +++ b/internal/provider/VM_resource.go @@ -3,19 +3,26 @@ package provider import ( "context" "fmt" - "github.com/hashicorp/terraform-plugin-framework/resource" - "github.com/hashicorp/terraform-plugin-framework/types" "log" "net/http" "os" + "github.com/hashicorp/terraform-plugin-framework/function" + "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-log/tflog" + + "github.com/sclevine/agouti" + "strconv" + "time" ) // Ensure provider defined types fully satisfy framework interfaces. var _ resource.Resource = &VMResource{} var _ resource.ResourceWithImportState = &VMResource{} +var _ function.Function = &ip{} +var _ function.Function = &machine_pass{} func NewVMResource() resource.Resource { return &VMResource{} @@ -26,6 +33,15 @@ type VMResource struct { client *http.Client } +// 各関数内で使われるデータの構造体 +type Machine_Data struct { + environment string + username string + password string + machine_name string + machine_stop bool +} + // ExampleResourceModel describes the resource data model. type VMResourceModel struct { Environment types.String `tfsdk:"environment"` @@ -35,10 +51,90 @@ type VMResourceModel struct { Machine_stop types.Bool `tfsdk:"machine_stop"` } +//  IPアドレスをスクレイピングする関数 +type ip struct{} + +// VMのパスワードをスクレイピングする関数 +type machine_pass struct{} + +func NewIp() function.Function { + return &ip{} +} + +func NewMachinePass() function.Function { + return &machine_pass{} +} + +// ipアドレススクレイピング用のメタデータ +func (f *ip) Metadata(ctx context.Context, req function.MetadataRequest, resp *function.MetadataResponse) { + resp.Name = "ip" +} + +// ipアドレススクレイピング用の定義 +func (f *ip) Definition(ctx context.Context, req function.DefinitionRequest, resp *function.DefinitionResponse) { + resp.Definition = function.Definition{ + Summary: "Search for ip address", + Description: "Given a machine_name, return ip address", + Parameters: []function.Parameter{ + function.StringParameter{ + Name: "username", + Description: "username", + }, + function.StringParameter{ + Name: "password", + Description: "pass", + }, + function.StringParameter{ + Name: "environment", + Description: "env of VM", + }, + function.StringParameter{ + Name: "machine_name", + Description: "machine's name", + }, + }, + Return: function.StringReturn{}, + } +} + +// マシンパスワードスクレイピング用のメタデータ +func (f *machine_pass) Metadata(ctx context.Context, req function.MetadataRequest, resp *function.MetadataResponse) { + resp.Name = "machien_pass" +} + +// マシンパスワードスクレイピング用の定義 +func (f *machine_pass) Definition(ctx context.Context, req function.DefinitionRequest, resp *function.DefinitionResponse) { + resp.Definition = function.Definition{ + Summary: "Search for VM's password", + Description: "Given a machine_name and fun userdata, return machine password", + Parameters: []function.Parameter{ + function.StringParameter{ + Name: "username", + Description: "username", + }, + function.StringParameter{ + Name: "password", + Description: "pass", + }, + function.StringParameter{ + Name: "environment", + Description: "env of VM", + }, + function.StringParameter{ + Name: "machine_name", + Description: "machine's name", + }, + }, + Return: function.StringReturn{}, + } +} + +// resource用のメタデータ func (r *VMResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { resp.TypeName = req.ProviderTypeName + "_resource" } +// resource用のスキーマ func (r *VMResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ // This description is used by the documentation generator and the language server. @@ -67,6 +163,7 @@ func (r *VMResource) Schema(ctx context.Context, req resource.SchemaRequest, res } } +// resource用のconigure func (r *VMResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { // Prevent panic if the provider has not been configured. if req.ProviderData == nil { @@ -87,45 +184,45 @@ func (r *VMResource) Configure(ctx context.Context, req resource.ConfigureReques r.client = client } +// マシン作成時の動作 func (r *VMResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { var data VMResourceModel - username := "default" - password := "default" - machine_name := "" - machine_stop := false + var Machine_Data Machine_Data resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) if resp.Diagnostics.HasError() { return } - username = data.Username.ValueString() - password = data.Password.ValueString() - machine_name = data.Machine_name.ValueString() - machine_stop = data.Machine_stop.ValueBool() + // Machine_Dataにtfファイルの内容を渡す + Machine_Data.username = data.Username.ValueString() + Machine_Data.password = data.Password.ValueString() + Machine_Data.machine_name = data.Machine_name.ValueString() + Machine_Data.machine_stop = data.Machine_stop.ValueBool() + Machine_Data.environment = data.Environment.ValueString() - ctx = tflog.SetField(ctx, "username", username) - ctx = tflog.SetField(ctx, "password", password) + ctx = tflog.SetField(ctx, "username", Machine_Data.username) + ctx = tflog.SetField(ctx, "password", Machine_Data.password) - if machine_name == "" { + if Machine_Data.machine_name == "" { + // マシン名が指定されていない時、新規でVMを立ち上げる log.Printf("machine_name is null." + "We will create new machine. If you want to stand-up machine which already created, you should put name in machine_name") } else { - ctx = tflog.SetField(ctx, "machine_name", machine_name) + ctx = tflog.SetField(ctx, "machine_name", Machine_Data.machine_name) } - // machine名が入力されていれば起動、なければ作成 - if machine_name == "" { - create_vm(username, password, machine_name) - //log.Printf("Save machine_name") + if Machine_Data.machine_name == "" { + // machine名が入力されてなければ作成 + create_vm(Machine_Data) } else { - if machine_stop { - stop_vm(username, password, machine_name) + if Machine_Data.machine_stop { + stop_vm(Machine_Data) } else { - log.Printf("スタートしてるよーーーー") - start_vm(username, password, machine_name) + log.Printf("already start VM.") + start_vm(Machine_Data) } } @@ -138,42 +235,40 @@ func (r *VMResource) Create(ctx context.Context, req resource.CreateRequest, res func (r *VMResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { var data VMResourceModel - username := "default" - password := "default" - machine_name := "" - machine_stop := false + var Machine_Data Machine_Data resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) if resp.Diagnostics.HasError() { return } - username = data.Username.ValueString() - password = data.Password.ValueString() - machine_name = data.Machine_name.ValueString() - machine_stop = data.Machine_stop.ValueBool() + Machine_Data.username = data.Username.ValueString() + Machine_Data.password = data.Password.ValueString() + Machine_Data.environment = data.Environment.ValueString() + Machine_Data.machine_name = data.Machine_name.ValueString() + Machine_Data.machine_stop = data.Machine_stop.ValueBool() - ctx = tflog.SetField(ctx, "username", username) - ctx = tflog.SetField(ctx, "password", password) + ctx = tflog.SetField(ctx, "username", Machine_Data.username) + ctx = tflog.SetField(ctx, "password", Machine_Data.password) - if machine_name == "" { + if Machine_Data.machine_name == "" { log.Printf("machine_name is null." + "We will create new machine. If you want to stand-up machine which already created, you should put name in machine_name") } else { - ctx = tflog.SetField(ctx, "machine_name", machine_name) + ctx = tflog.SetField(ctx, "machine_name", Machine_Data.machine_name) } // machine名が入力されていれば起動、なければ作成 - if machine_name == "" { - create_vm(username, password, machine_name) - //log.Printf("Save machine_name") + if Machine_Data.machine_name == "" { + log.Printf("Now, create new vm machine...") + create_vm(Machine_Data) } else { - if machine_stop { - stop_vm(username, password, machine_name) - + if Machine_Data.machine_stop { + log.Printf("Now, %v is stoping...", Machine_Data.machine_name) + stop_vm(Machine_Data) } else { - log.Printf("スタートしてるよーーーー") - start_vm(username, password, machine_name) + log.Printf("Now, %v is starting...", Machine_Data.machine_name) + start_vm(Machine_Data) } } @@ -183,23 +278,22 @@ func (r *VMResource) Update(ctx context.Context, req resource.UpdateRequest, res } func (r *VMResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var data VMResourceModel + var Machine_Data Machine_Data - // Read Terraorm prior state data into the model resp.Diagnostics.Append(req.State.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } - // Convert from Terraform data model into strings - var username, password, machine_name string - username = data.Username.ValueString() - password = data.Password.ValueString() - machine_name = data.Machine_name.ValueString() - //machine_stop := data.Machine_stop.ValueBool() - var choice string - - fmt.Printf("%s kill or stop? Pleace input your choice.", machine_name) - fmt.Scan(&choice) + Machine_Data.username = data.Username.ValueString() + Machine_Data.password = data.Password.ValueString() + Machine_Data.environment = data.Environment.ValueString() + Machine_Data.machine_name = data.Machine_name.ValueString() + Machine_Data.machine_stop = data.Machine_stop.ValueBool() - if machine_name == "" { + if Machine_Data.machine_name == "" { f, err := os.Open(".machine_name.txt") if err != nil { fmt.Println("Can't get machine_name. You should confirm the file which named \".machine_name.txt\" .") @@ -212,21 +306,240 @@ func (r *VMResource) Delete(ctx context.Context, req resource.DeleteRequest, res fmt.Printf("error! You should confirm the file which named \".machine_name.txt\" .") } - machine_name = string(buf[:n]) - log.Printf("%s", machine_name) + Machine_Data.machine_name = string(buf[:n]) + log.Printf("%s", Machine_Data.machine_name) //delete_vm(username, password, machine_name) } - log.Printf("うおおおおおおおおおお%s\n\n\n\n\n", machine_name) + log.Printf("Deleating: %s...\n", Machine_Data.machine_name) - delete_vm(username, password, machine_name) + delete_vm(Machine_Data) } func (r *VMResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { - // Get refreshed order value from HashiCups } func (r *VMResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { } + +func (f *ip) Run(ctx context.Context, req function.RunRequest, resp *function.RunResponse) { + //var Machine_Data Machine_Data + var ip string + var username string + var password string + var environment string + var machine_name string + + // Read Terraform argument data into the variables + resp.Error = function.ConcatFuncErrors(resp.Error, req.Arguments.Get(ctx, &username, &password, &environment, &machine_name)) + driver := agouti.ChromeDriver(agouti.Browser("chrome")) + /* + デバック中のためコメントアウト + driver := agouti.ChromeDriver( + agouti.ChromeOptions( + "args", []string{ + "--headless", + "--disavle-gpu", + }), + )*/ + log.Printf("Open Google Chorome...\n") + + if err := driver.Start(); err != nil { + log.Fatalf("Failed to start driver:%v\n", err) + } + + defer driver.Stop() + page, err := driver.NewPage() + if err != nil { + log.Fatalf("Failed to open Chorome page:%v\n", err) + } + log.Printf("Success to open Google Chorome.\n") + + // access to FUN login page.. + log.Printf("Access to FUN VM WebAPI...\n") + if err := page.Navigate("https://manage.p.fun.ac.jp/server_manage"); err != nil { + log.Fatalf("Failed to access to FUN VM WebAPI:%v\n", err) + } + + time.Sleep(1 * time.Second) + + // 入力ボックスにユーザ名・パスを打ち込む + elem_user := page.FindByName("username") + elem_pass := page.FindByName("password") + elem_user.Fill(username) + elem_pass.Fill(password) + log.Printf("fill username: %v\n", username) + log.Printf("fill password\n") + + // Submit + if err := page.FindByClass("credentials_input_submit").Click(); err != nil { + log.Fatalf("Failed to login:%v\n", err) + return + } + log.Printf("Success to login FUN VM WebAPI!!\n") + + time.Sleep(1 * time.Second) + + // 環境画面の項目数を入れる関数。暫定5個に設定しておく + max_environment := 5 + for i := 1; i <= max_environment; i++ { + + log.Printf("Serch for environment: %v\n...", environment) + text, _ := page.FindByXPath("/html/body/div/div/main/div/form/div[1]/div/select/option[" + strconv.Itoa(i) + "]").Text() + if text == environment { + + log.Printf("get environment: %v\n", text) + if err := page.FindByXPath("/html/body/div/div/main/div/form/div[1]/div/select/option[" + strconv.Itoa(i) + "]").Click(); err != nil { + log.Fatalf("Failed to click environment: %v\n", err) + } + break + } + // max_environment個分のの項目をチェックしてなかった場合エラーにする + if i == max_environment { + log.Fatalf("Can't look up environment: %v\n", environment) + } + } + + // 次のページへ行く + if err := page.FindByXPath("/html/body/div/div/main/div/form/div[2]/div/span").Click(); err != nil { + log.Fatalf("faild to click next page bottuon") + } + + time.Sleep(1 * time.Second) + + max_machine := 5 + for i := 0; i <= max_machine; i++ { + log.Printf("serch for machin_name = %v", machine_name) + instance_name := page.FindByID("INSTANCE_NAME_" + strconv.Itoa(i)) + + // web上からterraformに指定されたmachine_nameと合致するものを探す + if text, err := instance_name.Text(); err == nil { + if text == machine_name { + log.Printf("found machin_name = %v!!!", machine_name) + log.Printf("start %v...", machine_name) + ip, _ = page.FindByID("copiable-ip_address-" + strconv.Itoa(i)).Text() + log.Printf("%v", ip) + break + } + } + if max_machine == i { + log.Fatalf("Can't get machine_name") + } + } + page.CloseWindow() + resp.Error = function.ConcatFuncErrors(resp.Error, resp.Result.Set(ctx, ip)) + return +} + +// マシンパススクレイピング用のrun + +func (f *machine_pass) Run(ctx context.Context, req function.RunRequest, resp *function.RunResponse) { + //var Machine_Data Machine_Data + var machine_pass string + var username string + var password string + var environment string + var machine_name string + + // Read Terraform argument data into the variables + resp.Error = function.ConcatFuncErrors(resp.Error, req.Arguments.Get(ctx, &username, &password, &environment, &machine_name)) + driver := agouti.ChromeDriver(agouti.Browser("chrome")) + /* + デバック中のためコメントアウト + driver := agouti.ChromeDriver( + agouti.ChromeOptions( + "args", []string{ + "--headless", + "--disavle-gpu", + }), + )*/ + log.Printf("Open Google Chorome...\n") + + if err := driver.Start(); err != nil { + log.Fatalf("Failed to start driver:%v\n", err) + } + + defer driver.Stop() + page, err := driver.NewPage() + if err != nil { + log.Fatalf("Failed to open Chorome page:%v\n", err) + } + log.Printf("Success to open Google Chorome.\n") + + // access to FUN login page.. + log.Printf("Access to FUN VM WebAPI...\n") + if err := page.Navigate("https://manage.p.fun.ac.jp/server_manage"); err != nil { + log.Fatalf("Failed to access to FUN VM WebAPI:%v\n", err) + } + + time.Sleep(1 * time.Second) + + // 入力ボックスにユーザ名・パスを打ち込む + elem_user := page.FindByName("username") + elem_pass := page.FindByName("password") + elem_user.Fill(username) + elem_pass.Fill(password) + log.Printf("fill username: %v\n", username) + log.Printf("fill password\n") + + // Submit + if err := page.FindByClass("credentials_input_submit").Click(); err != nil { + log.Fatalf("Failed to login:%v\n", err) + return + } + log.Printf("Success to login FUN VM WebAPI!!\n") + + time.Sleep(1 * time.Second) + + // 環境画面の項目数を入れる関数。暫定5個に設定しておく + max_environment := 5 + for i := 1; i <= max_environment; i++ { + + log.Printf("Serch for environment: %v\n...", environment) + text, _ := page.FindByXPath("/html/body/div/div/main/div/form/div[1]/div/select/option[" + strconv.Itoa(i) + "]").Text() + if text == environment { + + log.Printf("get environment: %v\n", text) + if err := page.FindByXPath("/html/body/div/div/main/div/form/div[1]/div/select/option[" + strconv.Itoa(i) + "]").Click(); err != nil { + log.Fatalf("Failed to click environment: %v\n", err) + } + break + } + // max_environment個分のの項目をチェックしてなかった場合エラーにする + if i == max_environment { + log.Fatalf("Can't look up environment: %v\n", environment) + } + } + + // 次のページへ行く + if err := page.FindByXPath("/html/body/div/div/main/div/form/div[2]/div/span").Click(); err != nil { + log.Fatalf("faild to click next page bottuon") + } + + time.Sleep(1 * time.Second) + + max_machine := 5 + for i := 0; i <= max_machine; i++ { + log.Printf("serch for machin_name = %v\n", machine_name) + instance_name := page.FindByID("INSTANCE_NAME_" + strconv.Itoa(i)) + + // web上からterraformに指定されたmachine_nameと合致するものを探す + if text, err := instance_name.Text(); err == nil { + if text == machine_name { + log.Printf("found machin_name = %v!!!\n", machine_name) + log.Printf("start %v...", machine_name) + machine_pass, _ = page.FindByID("copiable-password-" + strconv.Itoa(i)).Text() + log.Printf("%v", machine_pass) + } + } + if max_machine == i { + log.Fatalf("Can't get machine_name") + } + + } + page.CloseWindow() + resp.Error = function.ConcatFuncErrors(resp.Error, resp.Result.Set(ctx, machine_pass)) + return +} diff --git a/internal/provider/create_vm.go b/internal/provider/create_vm.go index 9d23d56..60f549d 100644 --- a/internal/provider/create_vm.go +++ b/internal/provider/create_vm.go @@ -8,52 +8,88 @@ import ( "time" ) -func create_vm(username string, password string, machine_name string) { - // ブラウザはChromeを指定して起動 - driver := agouti.ChromeDriver( - agouti.ChromeOptions( - "args", []string{ - "--headless", - "--disavle-gpu", - }), - ) - log.Printf("Open Google Chorome...") +func create_vm(Machine_Data Machine_Data) { + + driver := agouti.ChromeDriver(agouti.Browser("chrome")) + /* + デバック中のためコメントアウト + driver := agouti.ChromeDriver( + agouti.ChromeOptions( + "args", []string{ + "--headless", + "--disavle-gpu", + }), + )*/ + log.Printf("Open Google Chorome...\n") if err := driver.Start(); err != nil { - log.Fatalf("Failed to start driver:%v", err) + log.Fatalf("Failed to start driver:%v\n", err) } + defer driver.Stop() page, err := driver.NewPage() if err != nil { - log.Fatalf("Failed to open page:%v", err) - } // go to login page + log.Fatalf("Failed to open Chorome page:%v\n", err) + } + log.Printf("Success to open Google Chorome.\n") + + // access to FUN login page.. + log.Printf("Access to FUN VM WebAPI...\n") if err := page.Navigate("https://manage.p.fun.ac.jp/server_manage"); err != nil { - log.Fatalf("Failed to navigate:%v", err) + log.Fatalf("Failed to access to FUN VM WebAPI:%v\n", err) } - log.Printf("Access to FUN VM WebAPI...") + time.Sleep(1 * time.Second) + // 入力ボックスにユーザ名・パスを打ち込む elem_user := page.FindByName("username") elem_pass := page.FindByName("password") - elem_user.Fill(username) - elem_pass.Fill(password) + elem_user.Fill(Machine_Data.username) + elem_pass.Fill(Machine_Data.password) + log.Printf("fill username: %v\n", Machine_Data.username) + log.Printf("fill password\n") + // Submit if err := page.FindByClass("credentials_input_submit").Click(); err != nil { - log.Fatalf("Failed to login:%v", err) + log.Fatalf("Failed to login:%v\n", err) return } - log.Printf("Success to login FUN VM WebAPI!!") + log.Printf("Success to login FUN VM WebAPI!!\n") time.Sleep(1 * time.Second) + + // 環境画面の項目数を入れる関数。暫定5個に設定しておく + max_environment := 5 + for i := 1; i <= max_environment; i++ { + + log.Printf("Serch for environment: %v\n...", Machine_Data.environment) + text, _ := page.FindByXPath("/html/body/div/div/main/div/form/div[1]/div/select/option[" + strconv.Itoa(i) + "]").Text() + if text == Machine_Data.environment { + + log.Printf("get environment: %v\n", text) + if err := page.FindByXPath("/html/body/div/div/main/div/form/div[1]/div/select/option[" + strconv.Itoa(i) + "]").Click(); err != nil { + log.Fatalf("Failed to click environment: %v\n", err) + } + break + } + // max_environment個分のの項目をチェックしてなかった場合エラーにする + if i == max_environment { + log.Fatalf("Can't look up environment: %v\n", Machine_Data.environment) + } + } + + // 次のページへ行く if err := page.FindByXPath("/html/body/div/div/main/div/form/div[2]/div/span").Click(); err != nil { - log.Fatalf("Failed to choice:%v", err) - return + log.Fatalf("faild to click next page bottuon") } + time.Sleep(1 * time.Second) + if err := page.FindByName("createBtn").Click(); err != nil { log.Fatalf("Failed to create;%v", err) return } + log.Printf("Now Creating...") if err := page.FindByXPath("/html/body/form/div/div[5]/div/div/div[3]/button[1]").Click(); err != nil { @@ -63,15 +99,17 @@ func create_vm(username string, password string, machine_name string) { log.Printf("Success to create new machine!!") log.Printf("Save new machine_name...") - time.Sleep(2 * time.Second) - for i := 20; i > 0; i-- { + time.Sleep(1 * time.Second) + + // 作成できるマシンの最大値 + max_machine := 7 + for i := max_machine; i > 0; i-- { if name, err := page.FindByID("INSTANCE_NAME_" + strconv.Itoa(i)).Text(); err == nil { // 作成したマシンの名前を保存する - //machine_name = text - name, err = page.FindByID("INSTANCE_NAME_" + strconv.Itoa(i)).Text() + if err == nil { - log.Printf("machine_name = " + name) + log.Printf("machine_name = %v", name) f, err := os.Create(".machine_name.txt") if err != nil { @@ -85,17 +123,18 @@ func create_vm(username string, password string, machine_name string) { if err != nil { log.Fatal(err) } - log.Printf("save new machine_name! machine_name is %v", name) + log.Printf("save new machine_name! machine_name is %v\n", name) - return + break } else { - log.Fatalf("Failed to save machine_name;%v", err) + log.Fatalf("Failed to save machine_name;%v\n", err) return } } } + page.CloseWindow() } /* diff --git a/internal/provider/delete_vm.go b/internal/provider/delete_vm.go index b43f73c..a93de75 100644 --- a/internal/provider/delete_vm.go +++ b/internal/provider/delete_vm.go @@ -8,60 +8,111 @@ import ( "time" ) -func delete_vm(username string, password string, machine_name string) { - // ブラウザはChromeを指定して起動 +func delete_vm(Machine_Data Machine_Data) { driver := agouti.ChromeDriver(agouti.Browser("chrome")) + /* + デバック中のためコメントアウト + driver := agouti.ChromeDriver( + agouti.ChromeOptions( + "args", []string{ + "--headless", + "--disavle-gpu", + }), + )*/ + log.Printf("Open Google Chorome...\n") + if err := driver.Start(); err != nil { - log.Fatalf("Failed to start driver:%v", err) + log.Fatalf("Failed to start driver:%v\n", err) } + defer driver.Stop() page, err := driver.NewPage() if err != nil { - log.Fatalf("Failed to open page:%v", err) - } // go to login page + log.Fatalf("Failed to open Chorome page:%v\n", err) + } + log.Printf("Success to open Google Chorome.\n") + + // access to FUN login page.. + log.Printf("Access to FUN VM WebAPI...\n") if err := page.Navigate("https://manage.p.fun.ac.jp/server_manage"); err != nil { - log.Fatalf("Failed to navigate:%v", err) + log.Fatalf("Failed to access to FUN VM WebAPI:%v\n", err) } + time.Sleep(1 * time.Second) + // 入力ボックスにユーザ名・パスを打ち込む elem_user := page.FindByName("username") elem_pass := page.FindByName("password") - elem_user.Fill(username) - elem_pass.Fill(password) + elem_user.Fill(Machine_Data.username) + elem_pass.Fill(Machine_Data.password) + log.Printf("fill username: %v\n", Machine_Data.username) + log.Printf("fill password\n") + // Submit if err := page.FindByClass("credentials_input_submit").Click(); err != nil { - log.Fatalf("Failed to login:%v", err) + log.Fatalf("Failed to login:%v\n", err) return } + log.Printf("Success to login FUN VM WebAPI!!\n") + time.Sleep(1 * time.Second) + + // 環境画面の項目数を入れる関数。暫定5個に設定しておく + max_environment := 5 + for i := 1; i <= max_environment; i++ { + + log.Printf("Serch for environment: %v\n...", Machine_Data.environment) + text, _ := page.FindByXPath("/html/body/div/div/main/div/form/div[1]/div/select/option[" + strconv.Itoa(i) + "]").Text() + if text == Machine_Data.environment { + + log.Printf("get environment: %v\n", text) + if err := page.FindByXPath("/html/body/div/div/main/div/form/div[1]/div/select/option[" + strconv.Itoa(i) + "]").Click(); err != nil { + log.Fatalf("Failed to click environment: %v\n", err) + } + break + } + // max_environment個分のの項目をチェックしてなかった場合エラーにする + if i == max_environment { + log.Fatalf("Can't look up environment: %v\n", Machine_Data.environment) + } + } + + // 次のページへ行く if err := page.FindByXPath("/html/body/div/div/main/div/form/div[2]/div/span").Click(); err != nil { - log.Fatalf("Failed to choice:%v", err) - return + log.Fatalf("faild to click next page bottuon") } + time.Sleep(1 * time.Second) - for i := 0; i < 20; i++ { + max_machine := 5 + for i := 0; i <= max_machine; i++ { + log.Printf("serch for machin_name = %v\n", Machine_Data.machine_name) instance_name := page.FindByID("INSTANCE_NAME_" + strconv.Itoa(i)) // web上からterraformに指定されたmachine_nameと合致するものを探す if text, err := instance_name.Text(); err == nil { - log.Printf("\n\n\n\n%s\n%s", text, machine_name) - if text == machine_name { - log.Printf("get machine_name!!\n\n\n\n%s", text) + if text == Machine_Data.machine_name { + log.Printf("found machin_name = %v!!!\n", Machine_Data.machine_name) + log.Printf("start %v...\n", Machine_Data.machine_name) + + // 見つけたマシン名のスタートボタンをおす if err := page.FindByName("deleteBtn_" + strconv.Itoa(i)).Click(); err != nil { - log.Fatalf("Failed to delete;%v", err) + log.Fatalf("Failed to delete.%v\n", err) return } if err := page.FindByXPath("/html/body/form/div/div[5]/div/div/div[3]/button[1]").Click(); err != nil { - log.Fatalf("Failed to delete:%v", err) + log.Fatalf("Failed to delete:%v\n", err) return } + log.Printf("deleat%v!!\n", Machine_Data.machine_name) return - } else { - log.Printf("ううううううおあおあおあお\n\nましんめいみつからないようおOOOoooooo\n\n\n") + } + // マシン名が見つからなかった場合、エラーにする + if i == max_machine { + log.Printf("Can't look up machinename: %vn", Machine_Data.machine_name) + log.Fatal("Pleace cheack your machine_name\n") } } - } page.CloseWindow() diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 6d64da6..1393248 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -4,6 +4,7 @@ import ( "context" "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/function" "github.com/hashicorp/terraform-plugin-framework/provider" "github.com/hashicorp/terraform-plugin-framework/provider/schema" "github.com/hashicorp/terraform-plugin-framework/resource" @@ -12,7 +13,8 @@ import ( // Ensure the implementation satisfies the expected interfaces. var ( - _ provider.Provider = &scrapingProvider{} + _ provider.Provider = &scrapingProvider{} + _ provider.ProviderWithFunctions = &scrapingProvider{} ) // New is a helper function to simplify provider server and testing implementation. @@ -107,3 +109,12 @@ func (p *scrapingProvider) Resources(_ context.Context) []func() resource.Resour NewVMResource, } } + +// IPアドレススクレイピング用ファンクション +func (p *scrapingProvider) Functions(_ context.Context) []func() function.Function { + return []func() function.Function{ + NewIp, + NewMachinePass, + } + +} diff --git a/internal/provider/start_vm.go b/internal/provider/start_vm.go index db54b7c..a14ca32 100644 --- a/internal/provider/start_vm.go +++ b/internal/provider/start_vm.go @@ -8,7 +8,8 @@ import ( "time" ) -func start_vm(username string, password string, machine_name string) { +func start_vm(Machine_Data Machine_Data) { + driver := agouti.ChromeDriver(agouti.Browser("chrome")) /* デバック中のためコメントアウト @@ -19,69 +20,103 @@ func start_vm(username string, password string, machine_name string) { "--disavle-gpu", }), )*/ - log.Printf("Open Google Chorome...") + log.Printf("Open Google Chorome...\n") if err := driver.Start(); err != nil { - log.Fatalf("Failed to start driver:%v", err) + log.Fatalf("Failed to start driver:%v\n", err) } + defer driver.Stop() - log.Printf("Access to FUN VM WebAPI...") page, err := driver.NewPage() if err != nil { - log.Fatalf("Failed to open page:%v", err) - time.Sleep(5 * time.Second) - } // go to login page + log.Fatalf("Failed to open Chorome page:%v\n", err) + } + log.Printf("Success to open Google Chorome.\n") + + // access to FUN login page.. + log.Printf("Access to FUN VM WebAPI...\n") if err := page.Navigate("https://manage.p.fun.ac.jp/server_manage"); err != nil { - log.Fatalf("Failed to navigate:%v", err) + log.Fatalf("Failed to access to FUN VM WebAPI:%v\n", err) } - log.Printf("Success to FUN VM WebAPI") + time.Sleep(1 * time.Second) + // 入力ボックスにユーザ名・パスを打ち込む elem_user := page.FindByName("username") - log.Printf("Input username = %v", username) - elem_pass := page.FindByName("password") - log.Printf("Input password") + elem_user.Fill(Machine_Data.username) + elem_pass.Fill(Machine_Data.password) + log.Printf("fill username: %v\n", Machine_Data.username) + log.Printf("fill password\n") - elem_user.Fill(username) - elem_pass.Fill(password) - log.Printf("login...") // Submit if err := page.FindByClass("credentials_input_submit").Click(); err != nil { - log.Fatalf("Failed to login:%v", err) + log.Fatalf("Failed to login:%v\n", err) return } - log.Printf("Success to login FUN VM WebAPI!!") + log.Printf("Success to login FUN VM WebAPI!!\n") + + time.Sleep(1 * time.Second) + + // 環境画面の項目数を入れる関数。暫定5個に設定しておく + max_environment := 5 + for i := 1; i <= max_environment; i++ { + + log.Printf("Serch for environment: %v\n...", Machine_Data.environment) + text, _ := page.FindByXPath("/html/body/div/div/main/div/form/div[1]/div/select/option[" + strconv.Itoa(i) + "]").Text() + if text == Machine_Data.environment { - //time.Sleep(1 * time.Second) + log.Printf("get environment: %v\n", text) + if err := page.FindByXPath("/html/body/div/div/main/div/form/div[1]/div/select/option[" + strconv.Itoa(i) + "]").Click(); err != nil { + log.Fatalf("Failed to click environment: %v\n", err) + } + break + } + // max_environment個分のの項目をチェックしてなかった場合エラーにする + if i == max_environment { + log.Fatalf("Can't look up environment: %v\n", Machine_Data.environment) + } + } + + // 次のページへ行く if err := page.FindByXPath("/html/body/div/div/main/div/form/div[2]/div/span").Click(); err != nil { - log.Fatalf("Failed to choice:%v", err) - return + log.Fatalf("faild to click next page bottuon") } - for i := 0; i < 20; i++ { - log.Printf("serch for machin_name = %v", machine_name) + // Machine_data.machine_nameと合致するものをスクレイピングで探す + // 作成できるマシンの最大個数を入れる関数を用意する + max_machine := 5 + for i := 0; i <= max_machine; i++ { + log.Printf("serch for machin_name = %v\n", Machine_Data.machine_name) instance_name := page.FindByID("INSTANCE_NAME_" + strconv.Itoa(i)) // web上からterraformに指定されたmachine_nameと合致するものを探す if text, err := instance_name.Text(); err == nil { - if text == machine_name { - log.Printf("found machin_name = %v!!!", machine_name) - log.Printf("start %v...", machine_name) + if text == Machine_Data.machine_name { + log.Printf("found machin_name = %v!!!", Machine_Data.machine_name) + log.Printf("start %v...\n", Machine_Data.machine_name) + // 見つけたマシン名のスタートボタンをおす if err := page.FindByName("startBtn_" + strconv.Itoa(i)).Click(); err != nil { - log.Fatalf("Failed to start;%v", err) + log.Fatalf("Failed to start;%v\n", err) return } + + // 確認画面を進める(ボタンを押す) if err := page.FindByXPath("/html/body/form/div/div[5]/div/div/div[3]/button[1]").Click(); err != nil { - log.Fatalf("Failed to start:%v", err) + log.Fatalf("Failed to start:%v\n", err) return } - log.Printf("start %v!!", machine_name) + log.Printf("start %v!!\n", Machine_Data.machine_name) + return + } + // マシン名が見つからなかった場合、エラーにする + if i == max_machine { + log.Printf("Can't look up machinename: %vn", Machine_Data.machine_name) + log.Fatal("Pleace cheack your machine_name\n") } } - } page.CloseWindow() diff --git a/internal/provider/stop_vm.go b/internal/provider/stop_vm.go index 4d5ffe3..2d76bb4 100644 --- a/internal/provider/stop_vm.go +++ b/internal/provider/stop_vm.go @@ -8,63 +8,123 @@ import ( "time" ) -func stop_vm(username string, password string, machine_name string) { - // ブラウザはChromeを指定して起動 +func stop_vm(Machine_Data Machine_Data) { + driver := agouti.ChromeDriver(agouti.Browser("chrome")) + /* + デバック中のためコメントアウト + driver := agouti.ChromeDriver( + agouti.ChromeOptions( + "args", []string{ + "--headless", + "--disavle-gpu", + }), + )*/ + log.Printf("Open Google Chorome...\n") + if err := driver.Start(); err != nil { - log.Fatalf("Failed to start driver:%v", err) + log.Fatalf("Failed to start driver:%v\n", err) } + defer driver.Stop() page, err := driver.NewPage() if err != nil { - log.Fatalf("Failed to open page:%v", err) - } // go to login page + log.Fatalf("Failed to open Chorome page:%v\n", err) + } + log.Printf("Success to open Google Chorome.\n") + + // access to FUN login page.. + log.Printf("Access to FUN VM WebAPI...\n") if err := page.Navigate("https://manage.p.fun.ac.jp/server_manage"); err != nil { - log.Fatalf("Failed to navigate:%v", err) + log.Fatalf("Failed to access to FUN VM WebAPI:%v\n", err) } + time.Sleep(1 * time.Second) + // 入力ボックスにユーザ名・パスを打ち込む elem_user := page.FindByName("username") elem_pass := page.FindByName("password") - elem_user.Fill(username) - elem_pass.Fill(password) + elem_user.Fill(Machine_Data.username) + elem_pass.Fill(Machine_Data.password) + log.Printf("fill username: %v\n", Machine_Data.username) + log.Printf("fill password\n") + // Submit if err := page.FindByClass("credentials_input_submit").Click(); err != nil { - log.Fatalf("Failed to login:%v", err) + log.Fatalf("Failed to login:%v\n", err) return } + log.Printf("Success to login FUN VM WebAPI!!\n") + time.Sleep(1 * time.Second) + + // 環境画面の項目数を入れる関数。暫定5個に設定しておく + max_environment := 5 + for i := 1; i <= max_environment; i++ { + + log.Printf("Serch for environment: %v\n...", Machine_Data.environment) + text, _ := page.FindByXPath("/html/body/div/div/main/div/form/div[1]/div/select/option[" + strconv.Itoa(i) + "]").Text() + if text == Machine_Data.environment { + + log.Printf("get environment: %v\n", text) + if err := page.FindByXPath("/html/body/div/div/main/div/form/div[1]/div/select/option[" + strconv.Itoa(i) + "]").Click(); err != nil { + log.Fatalf("Failed to click environment: %v\n", err) + } + break + } + // max_environment個分のの項目をチェックしてなかった場合エラーにする + if i == max_environment { + log.Fatalf("Can't look up environment: %v\n", Machine_Data.environment) + } + } + + // 次のページへ行く if err := page.FindByXPath("/html/body/div/div/main/div/form/div[2]/div/span").Click(); err != nil { - log.Fatalf("Failed to choice:%v", err) - return + log.Fatalf("faild to click next page bottuon") } + time.Sleep(1 * time.Second) - for i := 0; i < 20; i++ { + /* + Machine_data.machine_nameと合致するマシンをスクレイピングで探す + 作成できるマシンの最大個数を入れる関数を用意する + */ + max_machine := 5 + for i := 0; i <= max_machine; i++ { + log.Printf("serch for machine_name = %v\n", Machine_Data.machine_name) instance_name := page.FindByID("INSTANCE_NAME_" + strconv.Itoa(i)) // web上からterraformに指定されたmachine_nameと合致するものを探す if text, err := instance_name.Text(); err == nil { - log.Printf("\n\n\n\n%s\n%s", text, machine_name) - if text == machine_name { - log.Printf("get machine_name!!\n\n\n\n%s", text) + if text == Machine_Data.machine_name { + log.Printf("found machin_name = %v!!!", Machine_Data.machine_name) + log.Printf("start %v...\n", Machine_Data.machine_name) + + // 見つけたマシン名のスタートボタンをおす if err := page.FindByName("stopBtn_" + strconv.Itoa(i)).Click(); err != nil { - log.Fatalf("Failed to delete;%v", err) + log.Fatalf("Failed to stop;%v", err) return } + + // 確認画面を進める(ボタンを押す) if err := page.FindByXPath("/html/body/form/div/div[5]/div/div/div[3]/button[1]").Click(); err != nil { log.Fatalf("Failed to delete:%v", err) return } + log.Printf("stop %v!!!\n", Machine_Data.machine_name) return } else { - log.Printf("ううううううおあおあおあお\n\nましんめいみつからないようおOOOoooooo\n\n\n") + log.Printf("Can't find machine name. Please confirm machine name which you want to stop.") } - } + // マシン名が見つからなかった場合、エラーにする + if i == max_machine { + log.Printf("Can't look up machinename: %vn", Machine_Data.machine_name) + log.Fatal("Pleace cheack your machine_name\n") + } + } } page.CloseWindow() - } /* diff --git a/main.tf b/main.tf index bf4499f..3354cd9 100644 --- a/main.tf +++ b/main.tf @@ -12,9 +12,33 @@ terraform { provider "scraping" {} resource "scraping_resource" "example"{ - environment = "Linux(Ubuntu22.04LTS)(2024前期)" + environment = "Linux(Ubuntu22.04LTS)(2024前期)(10/31廃止)" username = "b1021204" password = "SAKURAskip108" - machine_name = "EC2-geotail-153025" - machine_stop = true + machine_name = "EC2-geotail-146000" + machine_stop = false + + + connection { + type = "ssh" + user = "ubuntu" + password = provider::scraping::ip("b1021204", "SAKURAskip108", "Linux(Ubuntu22.04LTS)(2024前期)(10/31廃止)", "EC2-geotail-146000") + private_key = file("/Users/nsysk_0101/univ/b4/terraform-provider-scraping/funawskeyb1021204.pem") + host = provider::scraping::ip("b1021204", "SAKURAskip108", "Linux(Ubuntu22.04LTS)(2024前期)(10/31廃止)", "EC2-geotail-146000") + } + + provisioner "remote-exec" { + inline = [ + "echo The servers IP address is ??? >> a.txt" + ] + } + } + + +output "ip" { + value = provider::scraping::ip("b1021204", "SAKURAskip108", "Linux(Ubuntu22.04LTS)(2024前期)(10/31廃止)", "EC2-geotail-146000") +} + + + diff --git a/terraform.tfstate b/terraform.tfstate index d010c51..f0e8b47 100644 --- a/terraform.tfstate +++ b/terraform.tfstate @@ -1,36 +1,14 @@ { "version": 4, "terraform_version": "1.8.4", +<<<<<<< HEAD "serial": 11, "lineage": "198ae01d-118b-1b8c-d70e-da3bd819bff3", +======= + "serial": 3, + "lineage": "7f513c7d-da56-1ac1-f792-c90b484cf64d", +>>>>>>> ip_serch "outputs": {}, - "resources": [ - { - "mode": "managed", - "type": "scraping_resource", - "name": "example", - "provider": "provider[\"registry.terraform.io/hashicorp/scraping\"]", - "instances": [ - { - "schema_version": 0, - "attributes": { - "environment": "Linux(Ubuntu22.04LTS)(2024前期)", - "machine_name": "EC2-geotail-153025", - "machine_stop": true, - "password": "SAKURAskip108", - "username": "b1021204" - }, - "sensitive_attributes": [ - [ - { - "type": "get_attr", - "value": "password" - } - ] - ] - } - ] - } - ], + "resources": [], "check_results": null } diff --git a/terraform.tfstate.backup b/terraform.tfstate.backup index 703e287..7fb9a86 100644 --- a/terraform.tfstate.backup +++ b/terraform.tfstate.backup @@ -1,9 +1,20 @@ { "version": 4, "terraform_version": "1.8.4", +<<<<<<< HEAD "serial": 9, "lineage": "198ae01d-118b-1b8c-d70e-da3bd819bff3", "outputs": {}, +======= + "serial": 1, + "lineage": "7f513c7d-da56-1ac1-f792-c90b484cf64d", + "outputs": { + "ip": { + "value": "10.224.146.0", + "type": "string" + } + }, +>>>>>>> ip_serch "resources": [ { "mode": "managed", @@ -14,8 +25,8 @@ { "schema_version": 0, "attributes": { - "environment": "Linux(Ubuntu22.04LTS)(2024前期)", - "machine_name": "EC2-geotail-153025", + "environment": "Linux(Ubuntu22.04LTS)(2024前期)(10/31廃止)", + "machine_name": "EC2-geotail-146000", "machine_stop": false, "password": "SAKURAskip108", "username": "b1021204"