graphql testin'

This commit is contained in:
Adam Mohammed
2023-07-27 09:37:38 -04:00
parent aca23ccf3f
commit ae8f4f4269
8 changed files with 404 additions and 2 deletions

View File

@@ -1,6 +1,11 @@
package emgql
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"time"
@@ -50,3 +55,41 @@ func New(options ...Option) (*Client, error) {
return client, nil
}
func (c *Client) graphquery(ctx context.Context, q string, vars map[string]string) (io.ReadCloser, error) {
qObj := struct {
Query string `json:"query"`
Variables map[string]string `json:"variables"`
}{
Query: q,
Variables: vars,
}
res, err := json.Marshal(qObj)
if err != nil {
return nil, fmt.Errorf("failed to marshal request object: %w", err)
}
req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.baseURL.String(), bytes.NewBuffer(res))
if err != nil {
return nil, fmt.Errorf("failed to build post request: %w", err)
}
req.Header.Add("content-type", "application/json")
resp, err := c.httpClient.Do(req)
if err != nil {
return nil, fmt.Errorf("failed to make post request: %w", err)
}
if resp.StatusCode != http.StatusOK {
b, err2 := io.ReadAll(resp.Body)
if err2 != nil {
return nil, fmt.Errorf("got unexpected response code [%d]: unable to parse request body: %v", resp.StatusCode, err)
}
return nil, fmt.Errorf("got unexpected response code [%d]: %s", resp.StatusCode, string(b))
}
return resp.Body, nil
}

View File

@@ -0,0 +1,85 @@
package emgql
import "go.equinixmetal.net/infra9-metal-bridge/internal/metal/models"
type organization struct {
ID string `json:"id"`
Name string `json:"name"`
Projects []project `json:"projects"`
Users []user `json:"users"`
}
func (o organization) ToOrganizationDetails() models.OrganizationDetails {
orgDetails := models.OrganizationDetails{
ID: o.ID,
Name: o.Name,
}
memberships := []*models.Membership[models.OrganizationDetails]{}
for _, u := range o.Users {
m := u.ToOrganizationMembership()
memberships = append(memberships, &m)
}
pDetails := []*models.ProjectDetails{}
for _, p := range o.Projects {
details := p.ToProjectDetails()
details.Organization = &orgDetails
pDetails = append(pDetails, &details)
}
orgDetails.Memberships = memberships
orgDetails.Projects = pDetails
return orgDetails
}
type project struct {
ID string `json:"id"`
Name string `json:"name"`
Users []user `json:"users"`
Organization struct {
ID string `json:"id"`
} `json:"organization"`
}
func (p project) ToProjectDetails() models.ProjectDetails {
memberships := []*models.Membership[models.ProjectDetails]{}
for _, u := range p.Users {
m := u.ToProjectMembership()
memberships = append(memberships, &m)
}
return models.ProjectDetails{
ID: p.ID,
Name: p.Name,
Memberships: memberships,
Organization: &models.OrganizationDetails{
ID: p.Organization.ID,
},
}
}
type user struct {
ID string `json:"id"`
Roles []string `json:"roles"`
}
func (u user) ToOrganizationMembership() models.Membership[models.OrganizationDetails] {
return models.Membership[models.OrganizationDetails]{
User: &models.UserDetails{
ID: u.ID,
},
Roles: u.Roles,
}
}
func (u user) ToProjectMembership() models.Membership[models.ProjectDetails] {
return models.Membership[models.ProjectDetails]{
User: &models.UserDetails{
ID: u.ID,
},
Roles: u.Roles,
}
}

View File

@@ -2,6 +2,9 @@ package emgql
import (
"context"
"encoding/json"
"fmt"
"io"
"go.infratographer.com/x/gidx"
@@ -10,5 +13,56 @@ import (
// GetOrganizationDetails fetches the organization id provided with its memberships.
func (c *Client) GetOrganizationDetails(ctx context.Context, id gidx.PrefixedID) (*models.OrganizationDetails, error) {
return nil, nil
q := `
query ($orgId: OrgId!){
organization(id: $orgId) {
id
name
users {
id
roles
}
projects {
id
name
}
}
}
`
variables := map[string]string{
"orgId": id.String(),
}
res, err := c.graphquery(ctx, q, variables)
if err != nil {
return nil, fmt.Errorf("emgql: error loading organization details: %w", err)
}
org, err := organizationFromResponse(res)
if err != nil {
return nil, fmt.Errorf("emgql: failed to parse response: %w", err)
}
out := org.ToOrganizationDetails()
return &out, nil
}
func organizationFromResponse(r io.ReadCloser) (organization, error) {
out := struct {
Data struct {
Organization organization `json:"organization"`
} `json:"data"`
}{}
body, err := io.ReadAll(r)
if err != nil {
return out.Data.Organization, fmt.Errorf("emgql: %w", err)
}
err = json.Unmarshal(body, &out)
if err != nil {
return out.Data.Organization, fmt.Errorf("emgql: %w", err)
}
return out.Data.Organization, nil
}

View File

@@ -2,6 +2,9 @@ package emgql
import (
"context"
"encoding/json"
"fmt"
"io"
"go.infratographer.com/x/gidx"
@@ -10,5 +13,55 @@ import (
// GetProjectDetails fetchs the provided project id with membership information.
func (c *Client) GetProjectDetails(ctx context.Context, id gidx.PrefixedID) (*models.ProjectDetails, error) {
return nil, nil
q := `
query ($projectId: ProjectId!){
project(id: $projectId) {
id
name
users {
id
roles
}
organization {
id
}
}
}
`
variables := map[string]string{
"projectId": id.String(),
}
res, err := c.graphquery(ctx, q, variables)
if err != nil {
return nil, fmt.Errorf("error loading project details: %w", err)
}
prj, err := projectFromResponse(res)
if err != nil {
return nil, fmt.Errorf("failed to parse response: %w", err)
}
out := prj.ToProjectDetails()
return &out, nil
}
func projectFromResponse(r io.ReadCloser) (project, error) {
out := struct {
Data struct {
Project project `json:"project"`
} `json:"data"`
}{}
body, err := io.ReadAll(r)
if err != nil {
return out.Data.Project, fmt.Errorf("emgql: %w", err)
}
err = json.Unmarshal(body, &out)
if err != nil {
return out.Data.Project, fmt.Errorf("emgql: %w", err)
}
return out.Data.Project, nil
}