github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/domain/apptemplate/converter.go (about) 1 package apptemplate 2 3 import ( 4 "bytes" 5 "database/sql" 6 "encoding/json" 7 "fmt" 8 "strings" 9 10 "k8s.io/client-go/util/jsonpath" 11 12 "github.com/kyma-incubator/compass/components/director/internal/model" 13 "github.com/kyma-incubator/compass/components/director/internal/repo" 14 "github.com/kyma-incubator/compass/components/director/pkg/apperrors" 15 "github.com/kyma-incubator/compass/components/director/pkg/graphql" 16 "github.com/kyma-incubator/compass/components/director/pkg/graphql/graphqlizer" 17 18 "github.com/pkg/errors" 19 ) 20 21 // AppConverter missing godoc 22 // 23 //go:generate mockery --name=AppConverter --output=automock --outpkg=automock --case=underscore --disable-version-string 24 type AppConverter interface { 25 CreateJSONInputGQLToJSON(in *graphql.ApplicationJSONInput) (string, error) 26 } 27 28 type converter struct { 29 appConverter AppConverter 30 webhookConverter WebhookConverter 31 } 32 33 // NewConverter missing godoc 34 func NewConverter(appConverter AppConverter, webhookConverter WebhookConverter) *converter { 35 return &converter{appConverter: appConverter, webhookConverter: webhookConverter} 36 } 37 38 // ToGraphQL missing godoc 39 func (c *converter) ToGraphQL(in *model.ApplicationTemplate) (*graphql.ApplicationTemplate, error) { 40 if in == nil { 41 return nil, nil 42 } 43 44 if in.ApplicationInputJSON == "" { 45 return nil, apperrors.NewInternalError("application input is empty") 46 } 47 48 gqlAppInput, err := c.graphqliseApplicationCreateInput(in.ApplicationInputJSON) 49 if err != nil { 50 return nil, errors.Wrapf(err, "while graphqlising application create input") 51 } 52 53 webhooks, err := c.webhooksToGraphql(in.Webhooks) 54 if err != nil { 55 return nil, err 56 } 57 58 return &graphql.ApplicationTemplate{ 59 ID: in.ID, 60 Name: in.Name, 61 Description: in.Description, 62 ApplicationNamespace: in.ApplicationNamespace, 63 Webhooks: webhooks, 64 ApplicationInput: gqlAppInput, 65 Placeholders: c.placeholdersToGraphql(in.Placeholders), 66 AccessLevel: graphql.ApplicationTemplateAccessLevel(in.AccessLevel), 67 }, nil 68 } 69 70 // MultipleToGraphQL missing godoc 71 func (c *converter) MultipleToGraphQL(in []*model.ApplicationTemplate) ([]*graphql.ApplicationTemplate, error) { 72 appTemplates := make([]*graphql.ApplicationTemplate, 0, len(in)) 73 for _, r := range in { 74 if r == nil { 75 continue 76 } 77 78 appTemplate, err := c.ToGraphQL(r) 79 if err != nil { 80 return nil, errors.Wrapf(err, "while converting application template") 81 } 82 appTemplates = append(appTemplates, appTemplate) 83 } 84 85 return appTemplates, nil 86 } 87 88 // InputFromGraphQL missing godoc 89 func (c *converter) InputFromGraphQL(in graphql.ApplicationTemplateInput) (model.ApplicationTemplateInput, error) { 90 var appCreateInput string 91 var err error 92 if in.ApplicationInput != nil { 93 appCreateInput, err = c.appConverter.CreateJSONInputGQLToJSON(in.ApplicationInput) 94 if err != nil { 95 return model.ApplicationTemplateInput{}, errors.Wrapf(err, "error occurred while converting GraphQL input to Application Template model with name %s", in.Name) 96 } 97 } 98 webhooks, err := c.webhookConverter.MultipleInputFromGraphQL(in.Webhooks) 99 if err != nil { 100 return model.ApplicationTemplateInput{}, errors.Wrapf(err, "error occurred while converting webhooks og GraphQL input to Application Template model with name %s", in.Name) 101 } 102 103 var labels map[string]interface{} 104 if in.Labels != nil { 105 labels = in.Labels 106 } 107 108 return model.ApplicationTemplateInput{ 109 Name: in.Name, 110 Description: in.Description, 111 ApplicationNamespace: in.ApplicationNamespace, 112 ApplicationInputJSON: appCreateInput, 113 Placeholders: c.placeholdersFromGraphql(in.Placeholders), 114 AccessLevel: model.ApplicationTemplateAccessLevel(in.AccessLevel), 115 Labels: labels, 116 Webhooks: webhooks, 117 }, nil 118 } 119 120 // UpdateInputFromGraphQL missing godoc 121 func (c *converter) UpdateInputFromGraphQL(in graphql.ApplicationTemplateUpdateInput) (model.ApplicationTemplateUpdateInput, error) { 122 var appCreateInput string 123 var err error 124 if in.ApplicationInput != nil { 125 appCreateInput, err = c.appConverter.CreateJSONInputGQLToJSON(in.ApplicationInput) 126 if err != nil { 127 return model.ApplicationTemplateUpdateInput{}, errors.Wrapf(err, "error occurred while converting GraphQL update input to Application Template model with name %s", in.Name) 128 } 129 } 130 131 webhooks, err := c.webhookConverter.MultipleInputFromGraphQL(in.Webhooks) 132 if err != nil { 133 return model.ApplicationTemplateUpdateInput{}, errors.Wrapf(err, "error occurred while converting webhooks og GraphQL input to Application Template model with name %s", in.Name) 134 } 135 136 return model.ApplicationTemplateUpdateInput{ 137 Name: in.Name, 138 Description: in.Description, 139 ApplicationNamespace: in.ApplicationNamespace, 140 ApplicationInputJSON: appCreateInput, 141 Placeholders: c.placeholdersFromGraphql(in.Placeholders), 142 AccessLevel: model.ApplicationTemplateAccessLevel(in.AccessLevel), 143 Labels: in.Labels, 144 Webhooks: webhooks, 145 }, nil 146 } 147 148 // ApplicationFromTemplateInputFromGraphQL missing godoc 149 func (c *converter) ApplicationFromTemplateInputFromGraphQL(appTemplate *model.ApplicationTemplate, in graphql.ApplicationFromTemplateInput) (model.ApplicationFromTemplateInput, error) { 150 values := make([]*model.ApplicationTemplateValueInput, 0, len(in.Values)) 151 if (in.PlaceholdersPayload != nil) && (len(in.Values) == 0) { 152 var obj interface{} 153 if err := json.Unmarshal([]byte(*in.PlaceholdersPayload), &obj); err != nil { 154 return model.ApplicationFromTemplateInput{}, err 155 } 156 157 parser := jsonpath.New("parser") 158 159 for _, placeholder := range appTemplate.Placeholders { 160 if placeholder.JSONPath != nil && len(*placeholder.JSONPath) > 0 { 161 if err := parser.Parse(fmt.Sprintf("{%s}", *placeholder.JSONPath)); err != nil { 162 return model.ApplicationFromTemplateInput{}, errors.Wrapf(err, "while parsing placeholder JSON path: %s", *placeholder.JSONPath) 163 } 164 165 buf := new(bytes.Buffer) 166 if err := parser.Execute(buf, obj); err != nil { 167 return model.ApplicationFromTemplateInput{}, errors.Wrapf(err, "while converting GraphQL input to Application From Template model. Value for Placeholder with name %s and path %s, not found in payload %s.", placeholder.Name, *placeholder.JSONPath, *in.PlaceholdersPayload) 168 } 169 170 valueInput := model.ApplicationTemplateValueInput{ 171 Placeholder: placeholder.Name, 172 Value: buf.String(), 173 } 174 values = append(values, &valueInput) 175 } else { 176 return model.ApplicationFromTemplateInput{}, errors.Errorf("error occurred while converting GraphQL input to Application From Template model. Placeholder with name %s, do not have the JSONPath.", placeholder.Name) 177 } 178 } 179 } else { 180 for _, value := range in.Values { 181 valueInput := model.ApplicationTemplateValueInput{ 182 Placeholder: value.Placeholder, 183 Value: value.Value, 184 } 185 values = append(values, &valueInput) 186 } 187 } 188 189 var labels map[string]interface{} 190 if in.Labels != nil { 191 labels = in.Labels 192 } 193 194 return model.ApplicationFromTemplateInput{ 195 TemplateName: in.TemplateName, 196 Values: values, 197 Labels: labels, 198 }, nil 199 } 200 201 // ToEntity missing godoc 202 func (c *converter) ToEntity(in *model.ApplicationTemplate) (*Entity, error) { 203 if in == nil { 204 return nil, nil 205 } 206 207 placeholders, err := c.placeholdersModelToJSON(in.Placeholders) 208 if err != nil { 209 return nil, errors.Wrap(err, "while converting placeholders from model to JSON") 210 } 211 212 return &Entity{ 213 ID: in.ID, 214 Name: in.Name, 215 Description: repo.NewNullableString(in.Description), 216 ApplicationNamespace: repo.NewNullableString(in.ApplicationNamespace), 217 ApplicationInputJSON: in.ApplicationInputJSON, 218 PlaceholdersJSON: placeholders, 219 AccessLevel: string(in.AccessLevel), 220 }, nil 221 } 222 223 // FromEntity missing godoc 224 func (c *converter) FromEntity(entity *Entity) (*model.ApplicationTemplate, error) { 225 if entity == nil { 226 return nil, nil 227 } 228 229 placeholders, err := c.placeholdersJSONToModel(entity.PlaceholdersJSON) 230 if err != nil { 231 return nil, errors.Wrap(err, "while converting placeholders from JSON to model") 232 } 233 234 return &model.ApplicationTemplate{ 235 ID: entity.ID, 236 Name: entity.Name, 237 Description: repo.StringPtrFromNullableString(entity.Description), 238 ApplicationNamespace: repo.StringPtrFromNullableString(entity.ApplicationNamespace), 239 ApplicationInputJSON: entity.ApplicationInputJSON, 240 Placeholders: placeholders, 241 AccessLevel: model.ApplicationTemplateAccessLevel(entity.AccessLevel), 242 }, nil 243 } 244 245 func (c *converter) graphqliseApplicationCreateInput(jsonAppInput string) (string, error) { 246 var gqlAppCreateInput graphql.ApplicationRegisterInput 247 err := json.Unmarshal([]byte(jsonAppInput), &gqlAppCreateInput) 248 if err != nil { 249 return "", errors.Wrap(err, "while unmarshaling application create input") 250 } 251 252 g := graphqlizer.Graphqlizer{} 253 gqlAppInput, err := g.ApplicationRegisterInputToGQL(gqlAppCreateInput) 254 if err != nil { 255 return "", errors.Wrap(err, "while graphqlising application create input") 256 } 257 gqlAppInput = strings.ReplaceAll(gqlAppInput, "\t", "") 258 gqlAppInput = strings.ReplaceAll(gqlAppInput, "\n", "") 259 return gqlAppInput, nil 260 } 261 262 func (c *converter) placeholdersJSONToModel(in sql.NullString) ([]model.ApplicationTemplatePlaceholder, error) { 263 if !in.Valid || in.String == "" { 264 return nil, nil 265 } 266 267 var placeholders []model.ApplicationTemplatePlaceholder 268 err := json.Unmarshal([]byte(in.String), &placeholders) 269 if err != nil { 270 return nil, err 271 } 272 273 return placeholders, nil 274 } 275 276 func (c *converter) placeholdersModelToJSON(in []model.ApplicationTemplatePlaceholder) (sql.NullString, error) { 277 result := sql.NullString{} 278 279 if in == nil { 280 return result, nil 281 } 282 283 placeholdersMarshalled, err := json.Marshal(in) 284 if err != nil { 285 return result, errors.Wrap(err, "while marshalling placeholders") 286 } 287 288 return repo.NewValidNullableString(string(placeholdersMarshalled)), nil 289 } 290 291 func (c *converter) placeholdersFromGraphql(in []*graphql.PlaceholderDefinitionInput) []model.ApplicationTemplatePlaceholder { 292 placeholders := make([]model.ApplicationTemplatePlaceholder, 0, len(in)) 293 for _, p := range in { 294 np := model.ApplicationTemplatePlaceholder{ 295 Name: p.Name, 296 Description: p.Description, 297 JSONPath: p.JSONPath, 298 Optional: p.Optional, 299 } 300 placeholders = append(placeholders, np) 301 } 302 return placeholders 303 } 304 305 func (c *converter) placeholdersToGraphql(in []model.ApplicationTemplatePlaceholder) []*graphql.PlaceholderDefinition { 306 placeholders := make([]*graphql.PlaceholderDefinition, 0, len(in)) 307 for _, p := range in { 308 np := graphql.PlaceholderDefinition{ 309 Name: p.Name, 310 Description: p.Description, 311 JSONPath: p.JSONPath, 312 Optional: p.Optional, 313 } 314 placeholders = append(placeholders, &np) 315 } 316 317 return placeholders 318 } 319 320 func (c *converter) webhooksToGraphql(in []model.Webhook) ([]graphql.Webhook, error) { 321 webhookPtrs := make([]*model.Webhook, len(in)) 322 for i := 0; i < len(in); i++ { 323 webhookPtrs[i] = &in[i] 324 } 325 gqlWebhookPtrs, err := c.webhookConverter.MultipleToGraphQL(webhookPtrs) 326 if err != nil { 327 return nil, errors.Wrap(err, "while converting webhooks to graphql") 328 } 329 gqlWebhooks := make([]graphql.Webhook, len(gqlWebhookPtrs)) 330 for i := 0; i < len(gqlWebhookPtrs); i++ { 331 gqlWebhooks[i] = *gqlWebhookPtrs[i] 332 } 333 return gqlWebhooks, nil 334 }