diff --git a/examples/provider-install-verification/main.tf b/examples/provider-install-verification/main.tf index 536f1af..41060ea 100644 --- a/examples/provider-install-verification/main.tf +++ b/examples/provider-install-verification/main.tf @@ -28,8 +28,8 @@ output "unicode_char" { */ resource "unicode_app" "example_app" { - id = "example 14" - name = "example app234" + id = "example14" + name = "example app234 for bob the builder the 2nd" description = "example" updated_at = "2021-07-01T00:00:00Z" created_at = "2021-07-01T00:00:00Z" @@ -39,6 +39,40 @@ output "name" { value = resource.unicode_app.example_app } +/*resource "unicode_unicode_string" "my_string2" { + app_id = unicode_app.example_app.id + value = "Hello, World!" +} + +output "my_string2" { + value = resource.unicode_unicode_string.my_string2 +} + +*/ + +resource "unicode_unicode_string" "my_string" { + app_id = unicode_app.example_app.id + value = "!" +} + +resource "unicode_unicode_string" "my_string2" { + app_id = unicode_unicode_string.my_string.app_id + value = "Hello, BOBS WORLD!" +} + +resource "unicode_unicode_string" "my_string3" { + app_id = unicode_unicode_string.my_string2.app_id + value = "Hello, TRUCE OF THE MATTER!" +} + +output "my_string2" { + value = resource.unicode_unicode_string.my_string2 +} + +output "my_string" { + value = resource.unicode_unicode_string.my_string +} + /*resource "unicode_unicode_string" "my_string" { app_id = unicode_app.example_app.id name = "Hello, World!" diff --git a/internal/provider/app_resource.go b/internal/provider/app_resource.go index 23c04e4..3ea9ebc 100644 --- a/internal/provider/app_resource.go +++ b/internal/provider/app_resource.go @@ -83,22 +83,23 @@ func (r *UnicodeAppResource) Create(_ context.Context, req resource.CreateReques } func (r *UnicodeAppResource) Read(_ context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { - var response *unicode_client.UnicodeAppModel + + var request *unicode_client.UnicodeAppModel + + req.State.Get(context.Background(), &request) // // - response, err := r.unicodeClient.GetApplications() + response, err := r.unicodeClient.GetApplication(request.Id) + if err != nil { - resp.Diagnostics.AddError("Unable to get Unicode Applications", err.Error()) - resp.Diagnostics.AddWarning("OLD ID ", response.Id) - return + //resp.Diagnostics.AddError("Unable to get Unicode Applications", err.Error()) + //return + resp.Diagnostics.AddWarning("May Not Be Created Yet", err.Error()) + req.State.Get(context.Background(), response) } - var old_state unicode_client.UnicodeAppModel - - req.State.Get(context.Background(), &old_state) - - diags := resp.State.Set(context.Background(), old_state) + diags := resp.State.Set(context.Background(), response) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return diff --git a/internal/provider/string_resource.go b/internal/provider/string_resource.go index 4a58179..6167990 100644 --- a/internal/provider/string_resource.go +++ b/internal/provider/string_resource.go @@ -2,28 +2,46 @@ package provider import ( "context" + unicode_client "terraform-provider-unicode/internal/unicode" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" ) -type UnicodeStringModel struct { - Id string `json:"id" tfsdk:"id"` - Name string `json:"name" tfsdk:"name"` - Index int `json:"index" tfsdk:"index"` - AppId string `json:"app_id" tfsdk:"app_id"` -} +var ( + _ resource.Resource = &unicodeStringResource{} + _ resource.ResourceWithConfigure = &unicodeStringResource{} +) func NewUnicodeStringResource() resource.Resource { return &unicodeStringResource{} } -type unicodeStringResource struct{} +type unicodeStringResource struct { + unicodeClient *unicode_client.UnicodeProviderClient +} func (r *unicodeStringResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { resp.TypeName = req.ProviderTypeName + "_unicode_string" } +func (r *unicodeStringResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { + //resp.State = req.NewState + //req.Config.Get(context.Background(), &plan) + + //r.unicodeClient = unicode_client.NewUnicodeProviderClient("test") + unicodeClient, ok := req.ProviderData.(*unicode_client.UnicodeProviderClient) + + if !ok { + //resp.Diagnostics.AddError("Unable to create client in resource", "Client is NULL After NewUnicodeProviderClient") + //return + resp.Diagnostics.AddWarning("Unable to create client in resource", "Client is NULL After NewUnicodeProviderClient") + unicodeClient = unicode_client.NewUnicodeProviderClient("bob") + } + + r.unicodeClient = unicodeClient +} + func (r *unicodeStringResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ @@ -31,14 +49,7 @@ func (r *unicodeStringResource) Schema(_ context.Context, _ resource.SchemaReque "app_id": schema.StringAttribute{ Required: true, }, - "name": schema.StringAttribute{ - Required: false, - Optional: true, - }, - "index": schema.NumberAttribute{ - Required: true, - }, - "id": schema.StringAttribute{ + "value": schema.StringAttribute{ Required: false, Optional: true, }, @@ -48,7 +59,7 @@ func (r *unicodeStringResource) Schema(_ context.Context, _ resource.SchemaReque func (r *unicodeStringResource) Create(_ context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { - var plan UnicodeStringModel + var plan unicode_client.UnicodeStringModel diags := req.Config.Get(context.Background(), &plan) @@ -58,25 +69,32 @@ func (r *unicodeStringResource) Create(_ context.Context, req resource.CreateReq return } - rr := &UnicodeStringModel{ - Id: plan.Id, - Name: plan.Name, - Index: plan.Index, - AppId: plan.AppId, + // Now Create the Conversionf + res, c, err := r.unicodeClient.AddConversionToApplication(plan) + + if err != nil { + resp.Diagnostics.AddError("Unable to Create Conversion", err.Error()) + return } - diags = resp.State.Set(context.Background(), rr) + diags = resp.State.Set(context.Background(), res) resp.Diagnostics.Append(diags...) + var conv string + for _, v := range c { + conv += "" + v.Value + } + + resp.Diagnostics.AddWarning("Conversion Created", conv) + if resp.Diagnostics.HasError() { return } - } func (r *unicodeStringResource) Read(_ context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { - var plan UnicodeStringModel + var plan unicode_client.UnicodeStringModel diags := req.State.Get(context.Background(), &plan) @@ -86,11 +104,13 @@ func (r *unicodeStringResource) Read(_ context.Context, req resource.ReadRequest return } - rr := &UnicodeStringModel{ - Id: plan.Id, - Name: plan.Name, - Index: plan.Index, - AppId: plan.AppId, + // Now Create the Conversion + rr, err := r.unicodeClient.GetConversionFromApplication(plan) + if err != nil { + resp.Diagnostics.AddWarning("Conversion Not Found", err.Error()) + + rr = &plan + //return } diags = resp.State.Set(context.Background(), rr) @@ -100,12 +120,47 @@ func (r *unicodeStringResource) Read(_ context.Context, req resource.ReadRequest if resp.Diagnostics.HasError() { return } + } func (r *unicodeStringResource) Update(_ context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { // Didn't Change + + // Not Implemented For Now .. + var plan unicode_client.UnicodeStringModel + + diags := req.Config.Get(context.Background(), &plan) + + resp.Diagnostics.Append(diags...) + + req.State.Set(context.Background(), plan) } func (r *unicodeStringResource) Delete(_ context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { // + var plan unicode_client.UnicodeStringModel + + diags := req.State.Get(context.Background(), &plan) + + resp.Diagnostics.Append(diags...) + + if resp.Diagnostics.HasError() { + return + } + + // Now Create the Conversion + _, err := r.unicodeClient.RemoveConversionFromApplication(plan) + + if err != nil { + resp.Diagnostics.AddError("Unable to Delete Conversion", err.Error()) + return + } + + diags = resp.State.Set(context.Background(), plan) + + resp.Diagnostics.Append(diags...) + + if resp.Diagnostics.HasError() { + return + } } diff --git a/internal/unicode/provider.go b/internal/unicode/provider.go index 652818d..263f13d 100644 --- a/internal/unicode/provider.go +++ b/internal/unicode/provider.go @@ -34,6 +34,16 @@ type UnicodeAppModelReq struct { Conversions []Conversion `json:"conversions"` } +type UnicodeAppModelReqString struct { + Id string `json:"appid" tfsdk:"id"` + Name string `json:"name" tfsdk:"name"` + Description string `json:"description" tfsdk:"description"` + Created_at string `json:"created_at" tfsdk:"created_at"` + Updated_at string `json:"updated_at" tfsdk:"updated_at"` + Conversions []Conversion `json:"conversions"` + User_id string `json:"user_id"` +} + type Conversion struct { Value string `json:"value"` } @@ -58,19 +68,18 @@ func (u *UnicodeProviderClient) GetUnicodeCharData(unicodeChar string) (*Unicode }, nil } -func (u *UnicodeProviderClient) GetApplications() (*UnicodeAppModel, error) { +func (u *UnicodeProviderClient) GetApplication(id string) (*UnicodeAppModel, error) { - client := &http.Client{} + jar, err := cookiejar.New(nil) + if err != nil { + return nil, err + } - return &UnicodeAppModel{ + client := &http.Client{ + Jar: jar, + } - Id: "1", - Name: "App 1", - Description: "App 1 Description", - Created_at: "2021-01-01", - Updated_at: "2021-01-01", - }, nil - // Now Assign Cookie Header of user=Username + //sET cOOKIE client.Jar.SetCookies(&url.URL{Scheme: "https", Host: host_url}, []*http.Cookie{ { Name: "user", @@ -78,26 +87,34 @@ func (u *UnicodeProviderClient) GetApplications() (*UnicodeAppModel, error) { }, }) - resp, err := client.Do(&http.Request{ + req := &http.Request{ Method: "GET", - URL: &url.URL{Scheme: "https", Host: endpoint_url + "/saved"}, - }) + URL: &url.URL{Scheme: "https", Host: host_url, Path: "/Prod/api/v1/application/" + id}, + Body: nil, + Header: make(http.Header), + } + + res, err := client.Do(req) if err != nil { return nil, err } - var apps []UnicodeAppModel + if res.StatusCode != http.StatusOK { + return nil, fmt.Errorf("unexpected status code %d", res.StatusCode) + } + + var app UnicodeAppModel // Decode JSON - err = json.NewDecoder(resp.Body).Decode(&apps) + err = json.NewDecoder(res.Body).Decode(&app) if err != nil { return nil, err } - //return &apps, nil - return &(apps[0]), nil + return &app, nil + } func (u *UnicodeProviderClient) CreateApplication(model UnicodeAppModel) (*UnicodeAppModel, error) { @@ -120,13 +137,14 @@ func (u *UnicodeProviderClient) CreateApplication(model UnicodeAppModel) (*Unico }) // turn model into model request - model_req := UnicodeAppModelReq{ + model_req := UnicodeAppModelReqString{ Id: model.Id, Name: model.Name, Description: model.Description, Created_at: model.Created_at, Updated_at: model.Updated_at, Conversions: []Conversion{}, + User_id: u.Username, } body_bytes, err := json.Marshal(model_req) @@ -225,3 +243,239 @@ func (u *UnicodeProviderClient) UpdateApplication(model UnicodeAppModel) (*Unico return &model, nil } + +func (u *UnicodeProviderClient) AddConversionToApplication(plan UnicodeStringModel) (*UnicodeStringModel, []Conversion, error) { + + if u.Username == "" { + return nil, []Conversion{}, fmt.Errorf("Username is Empty") + } + + var current_app UnicodeAppModelReqString + + jar, err := cookiejar.New(nil) + if err != nil { + return nil, []Conversion{}, err + } + + client := &http.Client{ + Jar: jar, + } + + //Set Cookie + client.Jar.SetCookies(&url.URL{Scheme: "https", Host: host_url}, []*http.Cookie{ + { + Name: "user", + Value: u.Username, + }, + }) + + //Find Current Application State + get_app_req := &http.Request{ + Method: "GET", + URL: &url.URL{Scheme: "https", Host: host_url, Path: "/Prod/api/v1/application/" + plan.AppId}, + Body: nil, + Header: make(http.Header), + } + + res, err := client.Do(get_app_req) + + if err != nil { + return nil, []Conversion{}, err + } + + if res.StatusCode != http.StatusOK { + return nil, []Conversion{}, fmt.Errorf("unexpected status get code %d", res.StatusCode) + } + + // Decode JSON + err = json.NewDecoder(res.Body).Decode(¤t_app) + + //Now Append the Conversion to the Application + + var conv Conversion + conv.Value = plan.Value + + var conversions []Conversion + + conversions = append(current_app.Conversions, conv) + + current_app.Conversions = conversions + + current_app.User_id = u.Username + + //Now, Update the Application + body_bytes, err := json.Marshal(current_app) + if err != nil { + return nil, []Conversion{}, err + } + + update_req := &http.Request{ + Method: "POST", + URL: &url.URL{Scheme: "https", Host: host_url, Path: "/Prod/api/v1/application"}, + Body: io.NopCloser(bytes.NewReader(body_bytes)), + Header: make(http.Header), + } + + res, err = client.Do(update_req) + + if err != nil { + return nil, []Conversion{}, err + } + + if res.StatusCode != http.StatusOK { + return nil, []Conversion{}, fmt.Errorf("unexpected status post code %d", res.StatusCode) + } + + return &plan, current_app.Conversions, nil +} + +func (u *UnicodeProviderClient) RemoveConversionFromApplication(plan UnicodeStringModel) (*UnicodeAppModel, error) { + + var current_app UnicodeAppModelReq + + jar, err := cookiejar.New(nil) + if err != nil { + return nil, err + } + + client := &http.Client{ + Jar: jar, + } + + //Set Cookie + client.Jar.SetCookies(&url.URL{Scheme: "https", Host: host_url}, []*http.Cookie{ + { + Name: "user", + Value: u.Username, + }, + }) + + //Find Current Application State + get_app_req := &http.Request{ + Method: "GET", + URL: &url.URL{Scheme: "https", Host: host_url, Path: "/Prod/api/v1/application/" + plan.AppId}, + Body: nil, + Header: make(http.Header), + } + + res, err := client.Do(get_app_req) + + if err != nil { + return nil, err + } + + // Decode JSON + err = json.NewDecoder(res.Body).Decode(¤t_app) + + // Now Find Current String With That Value and Remove it + var new_conversions []Conversion + + for _, v := range current_app.Conversions { + if v.Value != plan.Value { + new_conversions = append(new_conversions, v) + } + } + + current_app.Conversions = new_conversions + + //Now, Update the Application + body_bytes, err := json.Marshal(current_app) + + if err != nil { + return nil, err + } + + update_req := &http.Request{ + Method: "POST", + URL: &url.URL{Scheme: "https", Host: host_url, Path: "/Prod/api/v1/application/" + plan.AppId}, + Body: io.NopCloser(bytes.NewReader(body_bytes)), + Header: make(http.Header), + } + + _, err = client.Do(update_req) + + if err != nil { + return nil, err + } + + return nil, nil + +} + +type UnicodeStringModel struct { + Value string `json:"value" tfsdk:"value"` + AppId string `json:"app_id" tfsdk:"app_id"` +} + +func (u *UnicodeProviderClient) GetConversionFromApplication(model UnicodeStringModel) (*UnicodeStringModel, error) { + + var plan Conversion + + plan.Value = model.Value + + jar, err := cookiejar.New(nil) + if err != nil { + return nil, err + } + + client := &http.Client{ + Jar: jar, + } + + //Set Cookie + client.Jar.SetCookies(&url.URL{Scheme: "https", Host: host_url}, []*http.Cookie{ + { + Name: "user", + Value: u.Username, + }, + }) + + //Now, Get The Application and find the Conversions + get_convo_req := &http.Request{ + Method: "GET", + URL: &url.URL{Scheme: "https", Host: host_url, Path: "/Prod/api/v1/application/" + model.AppId}, + Body: nil, + Header: make(http.Header), + } + + res, err := client.Do(get_convo_req) + + if err != nil { + return nil, err + } + + var Application UnicodeAppModelReq + + // Decode JSON + err = json.NewDecoder(res.Body).Decode(&Application) + + if err != nil { + return nil, err + } + + //Now Append the Conversion to the Application + Application.Conversions = append(Application.Conversions, plan) + + //Now, Update the Application + body_bytes, err := json.Marshal(Application) + if err != nil { + return nil, err + } + + update_req := &http.Request{ + Method: "POST", + URL: &url.URL{Scheme: "https", Host: host_url, Path: "/Prod/api/v1/application/" + model.AppId}, + Body: io.NopCloser(bytes.NewReader(body_bytes)), + Header: make(http.Header), + } + + res, err = client.Do(update_req) + + if err != nil { + return nil, err + } + + //Now + + return &model, nil +}