github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/systemfetcher/template_test.go (about) 1 package systemfetcher_test 2 3 import ( 4 "context" 5 "testing" 6 7 "github.com/kyma-incubator/compass/components/director/pkg/str" 8 9 "github.com/kyma-incubator/compass/components/director/internal/model" 10 "github.com/kyma-incubator/compass/components/director/internal/systemfetcher" 11 "github.com/kyma-incubator/compass/components/director/internal/systemfetcher/automock" 12 "github.com/pkg/errors" 13 "github.com/stretchr/testify/mock" 14 "github.com/stretchr/testify/require" 15 ) 16 17 func TestNewTemplateRenderer(t *testing.T) { 18 t.Run("Creates a new renderer", func(t *testing.T) { 19 appInputOverride := `{"name":"{{name}}"}` 20 templateSvc := &automock.ApplicationTemplateService{} 21 convSvc := &automock.ApplicationConverter{} 22 convSvc.On("CreateInputJSONToModel", context.TODO(), appInputOverride).Return(model.ApplicationRegisterInput{}, nil).Once() 23 defer mock.AssertExpectationsForObjects(t, templateSvc, convSvc) 24 tr, err := systemfetcher.NewTemplateRenderer(templateSvc, convSvc, appInputOverride, []systemfetcher.PlaceholderMapping{}) 25 26 require.NoError(t, err) 27 require.NotNil(t, tr) 28 }) 29 t.Run("Fails to create a new renderer when the override application input is not valid", func(t *testing.T) { 30 invalidOverrides := "invalid" 31 expectedErr := errors.New("test err") 32 33 templateSvc := &automock.ApplicationTemplateService{} 34 convSvc := &automock.ApplicationConverter{} 35 convSvc.On("CreateInputJSONToModel", context.TODO(), invalidOverrides).Return(model.ApplicationRegisterInput{}, expectedErr).Once() 36 defer mock.AssertExpectationsForObjects(t, templateSvc, convSvc) 37 38 tr, err := systemfetcher.NewTemplateRenderer(templateSvc, convSvc, invalidOverrides, []systemfetcher.PlaceholderMapping{}) 39 require.ErrorIs(t, err, expectedErr) 40 require.Nil(t, tr) 41 }) 42 } 43 func TestApplicationRegisterInputFromTemplate(t *testing.T) { 44 const ( 45 appTemplateID = "appTmp1" 46 appRegisterInputJSON = `{"name":"test"}` 47 appInputOverride = `{"name":"testtest"}` 48 ) 49 var ( 50 optionalFalse = false 51 ) 52 53 placeholdersMappings := []systemfetcher.PlaceholderMapping{ 54 { 55 PlaceholderName: "name", 56 SystemKey: "$.displayName", 57 }, 58 } 59 60 appTemplate := &model.ApplicationTemplate{ 61 ID: appTemplateID, 62 ApplicationInputJSON: `{"name":"testtest"}`, 63 } 64 65 appTemplateWithOverrides := &model.ApplicationTemplate{ 66 ID: appTemplateID, 67 Placeholders: []model.ApplicationTemplatePlaceholder{ 68 {Name: "name", JSONPath: str.Ptr("$.displayName"), Optional: &optionalFalse}, 69 }, 70 ApplicationInputJSON: appInputOverride, 71 } 72 73 testSystem := systemfetcher.System{ 74 SystemPayload: map[string]interface{}{ 75 "systemNumber": "123", 76 "displayName": "test", 77 "productDescription": "test", 78 "baseUrl": "http://test", 79 "infrastructureProvider": "test", 80 }, 81 TemplateID: "123", 82 } 83 84 appTemplateSvcNoErrors := func(testSystem systemfetcher.System, _ error) *automock.ApplicationTemplateService { 85 svc := &automock.ApplicationTemplateService{} 86 inputValues := fixInputValuesForSystem(t, testSystem) 87 template := &model.ApplicationTemplate{ 88 ID: appTemplateID, 89 ApplicationInputJSON: `{ "name": "testtest"}`, 90 } 91 svc.On("Get", context.TODO(), testSystem.TemplateID).Return(template, nil).Once() 92 svc.On("PrepareApplicationCreateInputJSON", appTemplateWithOverrides, inputValues).Return(appRegisterInputJSON, nil).Once() 93 return svc 94 } 95 appConvSvcNoErrors := func(testSystem systemfetcher.System, _ error) *automock.ApplicationConverter { 96 appInput := fixAppInputBySystem(t, testSystem) 97 conv := &automock.ApplicationConverter{} 98 conv.On("CreateInputJSONToModel", context.TODO(), appRegisterInputJSON).Return(appInput, nil).Once() 99 return conv 100 } 101 102 type testCase struct { 103 name string 104 system systemfetcher.System 105 expectedErr error 106 appInputOverride string 107 placeholderMappings []systemfetcher.PlaceholderMapping 108 setupAppTemplateSvc func(testSystem systemfetcher.System, potentialErr error) *automock.ApplicationTemplateService 109 setupAppConverter func(testSystem systemfetcher.System, potentialErr error) *automock.ApplicationConverter 110 } 111 tests := []testCase{ 112 { 113 name: "Succeeds", 114 system: testSystem, 115 appInputOverride: appInputOverride, 116 placeholderMappings: placeholdersMappings, 117 setupAppTemplateSvc: appTemplateSvcNoErrors, 118 setupAppConverter: appConvSvcNoErrors, 119 }, 120 { 121 name: "Succeeds when app template should be enriched with additional labels", 122 system: testSystem, 123 appInputOverride: `{"name":"{{name}}","labels":{"legacy":"true"}}`, 124 placeholderMappings: placeholdersMappings, 125 setupAppTemplateSvc: func(testSystem systemfetcher.System, _ error) *automock.ApplicationTemplateService { 126 resultTemplate := *appTemplateWithOverrides 127 resultTemplate.ApplicationInputJSON = `{"integrationSystemID":"a8396508-66be-4dc7-b463-577809289941","labels":{"legacy":"true","tenant":"123"},"name":"test1"}` 128 appTemplateFromDB := model.ApplicationTemplate{ 129 ID: appTemplateID, 130 ApplicationInputJSON: `{ "name": "testtest"}`, 131 } 132 appTemplateFromDB.ApplicationInputJSON = `{"name": "test1","labels":{"tenant":"123"},"integrationSystemID":"a8396508-66be-4dc7-b463-577809289941"}` 133 134 svc := &automock.ApplicationTemplateService{} 135 svc.On("Get", context.TODO(), testSystem.TemplateID).Return(&appTemplateFromDB, nil).Once() 136 svc.On("PrepareApplicationCreateInputJSON", &resultTemplate, fixInputValuesForSystem(t, testSystem)).Return(appRegisterInputJSON, nil).Once() 137 return svc 138 }, 139 setupAppConverter: appConvSvcNoErrors, 140 }, 141 { 142 name: "Succeeds when app template has placeholders", 143 system: testSystem, 144 appInputOverride: `{"name":"{{name}}"}`, 145 placeholderMappings: placeholdersMappings, 146 setupAppTemplateSvc: func(testSystem systemfetcher.System, _ error) *automock.ApplicationTemplateService { 147 resultTemplate := model.ApplicationTemplate{ 148 ID: appTemplateID, 149 Placeholders: []model.ApplicationTemplatePlaceholder{ 150 {Name: "name", JSONPath: str.Ptr("$.displayName"), Optional: &optionalFalse}, 151 }, 152 ApplicationInputJSON: `{"integrationSystemID":"a8396508-66be-4dc7-b463-577809289941","labels":{"tenant":"123"},"name":"test1"}`, 153 } 154 appTemplateFromDB := model.ApplicationTemplate{ 155 ID: appTemplateID, 156 Placeholders: []model.ApplicationTemplatePlaceholder{ 157 {Name: "name", JSONPath: str.Ptr("$.displayName"), Optional: &optionalFalse}, 158 }, 159 ApplicationInputJSON: `{ "name": "test1","labels":{"tenant":"123"},"integrationSystemID":"a8396508-66be-4dc7-b463-577809289941"}`, 160 } 161 162 svc := &automock.ApplicationTemplateService{} 163 svc.On("Get", context.TODO(), testSystem.TemplateID).Return(&appTemplateFromDB, nil).Once() 164 svc.On("PrepareApplicationCreateInputJSON", &resultTemplate, fixInputValuesForSystemWhichAppTemplateHasPlaceholders(t, testSystem)).Return(`{"name":"test"}`, nil).Once() 165 return svc 166 }, 167 setupAppConverter: func(testSystem systemfetcher.System, _ error) *automock.ApplicationConverter { 168 appInput := fixAppInputBySystem(t, testSystem) 169 conv := &automock.ApplicationConverter{} 170 conv.On("CreateInputJSONToModel", context.TODO(), `{"name":"test"}`).Return(appInput, nil).Once() 171 return conv 172 }, 173 }, 174 { 175 name: "Fails when app template has placeholders without assigned values", 176 system: testSystem, 177 expectedErr: errors.New("missing or empty key \"$.nonexistentKey\" in system payload"), 178 appInputOverride: appInputOverride, 179 placeholderMappings: []systemfetcher.PlaceholderMapping{ 180 { 181 PlaceholderName: "name", 182 SystemKey: "$.displayName", 183 }, 184 { 185 PlaceholderName: "description", 186 SystemKey: "$.nonexistentKey", 187 }, 188 }, 189 setupAppTemplateSvc: func(testSystem systemfetcher.System, _ error) *automock.ApplicationTemplateService { 190 svc := &automock.ApplicationTemplateService{} 191 //inputValues := fixInputValuesForSystem(testSystem) 192 svc.On("Get", context.TODO(), testSystem.TemplateID).Return(appTemplate, nil).Once() 193 return svc 194 }, 195 setupAppConverter: func(testSystem systemfetcher.System, _ error) *automock.ApplicationConverter { 196 return &automock.ApplicationConverter{} 197 }, 198 }, 199 { 200 name: "Fails when app input from template cannot be unmarshalled into a map", 201 system: testSystem, 202 expectedErr: errors.New("while unmarshaling original application input"), 203 appInputOverride: `{"description":"{{description}}","labels":"hello"}`, 204 placeholderMappings: placeholdersMappings, 205 setupAppTemplateSvc: func(testSystem systemfetcher.System, _ error) *automock.ApplicationTemplateService { 206 appTemplateFromDB := *appTemplate 207 appTemplateFromDB.ApplicationInputJSON = `` 208 209 svc := &automock.ApplicationTemplateService{} 210 svc.On("Get", context.TODO(), testSystem.TemplateID).Return(&appTemplateFromDB, nil).Once() 211 return svc 212 }, 213 setupAppConverter: func(testSystem systemfetcher.System, _ error) *automock.ApplicationConverter { 214 return &automock.ApplicationConverter{} 215 }, 216 }, 217 { 218 name: "Fails when app input from override cannot be unmarshalled into a map", 219 system: testSystem, 220 expectedErr: errors.New("while unmarshaling override application input"), 221 appInputOverride: ``, 222 placeholderMappings: placeholdersMappings, 223 setupAppTemplateSvc: func(testSystem systemfetcher.System, _ error) *automock.ApplicationTemplateService { 224 appTemplateFromDB := *appTemplate 225 appTemplateFromDB.ApplicationInputJSON = `{"name": "{{display-name}}"}` 226 227 svc := &automock.ApplicationTemplateService{} 228 svc.On("Get", context.TODO(), testSystem.TemplateID).Return(&appTemplateFromDB, nil).Once() 229 return svc 230 }, 231 setupAppConverter: func(testSystem systemfetcher.System, _ error) *automock.ApplicationConverter { 232 return &automock.ApplicationConverter{} 233 }, 234 }, 235 { 236 name: "Fails when template cannot be fetched", 237 system: testSystem, 238 appInputOverride: appInputOverride, 239 placeholderMappings: placeholdersMappings, 240 expectedErr: errors.New("cannot get template"), 241 setupAppTemplateSvc: func(testSystem systemfetcher.System, err error) *automock.ApplicationTemplateService { 242 svc := &automock.ApplicationTemplateService{} 243 svc.On("Get", context.TODO(), testSystem.TemplateID).Return(nil, err).Once() 244 return svc 245 }, 246 setupAppConverter: func(testSystem systemfetcher.System, _ error) *automock.ApplicationConverter { 247 return &automock.ApplicationConverter{} 248 }, 249 }, 250 { 251 name: "Fails when app input JSON cannot be prepared", 252 system: testSystem, 253 appInputOverride: appInputOverride, 254 placeholderMappings: placeholdersMappings, 255 expectedErr: errors.New("cannot prepare input json"), 256 setupAppTemplateSvc: func(testSystem systemfetcher.System, err error) *automock.ApplicationTemplateService { 257 svc := &automock.ApplicationTemplateService{} 258 inputValues := fixInputValuesForSystem(t, testSystem) 259 template := &model.ApplicationTemplate{ 260 ID: appTemplateID, 261 ApplicationInputJSON: `{ "name": "testtest"}`, 262 } 263 svc.On("Get", context.TODO(), testSystem.TemplateID).Return(template, nil).Once() 264 svc.On("PrepareApplicationCreateInputJSON", appTemplateWithOverrides, inputValues).Return("", err).Once() 265 return svc 266 }, 267 setupAppConverter: func(testSystem systemfetcher.System, _ error) *automock.ApplicationConverter { 268 return &automock.ApplicationConverter{} 269 }, 270 }, 271 { 272 name: "Fails when app input cannot be prepared", 273 system: testSystem, 274 appInputOverride: appInputOverride, 275 placeholderMappings: placeholdersMappings, 276 expectedErr: errors.New("cannot prepare input"), 277 setupAppTemplateSvc: appTemplateSvcNoErrors, 278 setupAppConverter: func(testSystem systemfetcher.System, err error) *automock.ApplicationConverter { 279 conv := &automock.ApplicationConverter{} 280 conv.On("CreateInputJSONToModel", context.TODO(), appRegisterInputJSON).Return(model.ApplicationRegisterInput{}, err).Once() 281 return conv 282 }, 283 }, 284 } 285 for _, test := range tests { 286 t.Run(test.name, func(t *testing.T) { 287 // GIVEN 288 templateSvc := test.setupAppTemplateSvc(test.system, test.expectedErr) 289 convSvc := test.setupAppConverter(test.system, test.expectedErr) 290 convSvc.On("CreateInputJSONToModel", context.TODO(), test.appInputOverride).Return(model.ApplicationRegisterInput{}, nil).Once() 291 tr, err := systemfetcher.NewTemplateRenderer(templateSvc, convSvc, test.appInputOverride, test.placeholderMappings) 292 require.NoError(t, err) 293 294 defer mock.AssertExpectationsForObjects(t, templateSvc, convSvc) 295 296 // WHEN 297 regIn, err := tr.ApplicationRegisterInputFromTemplate(context.TODO(), testSystem) 298 299 // THEN 300 if test.expectedErr != nil { 301 require.Error(t, err) 302 require.Contains(t, err.Error(), test.expectedErr.Error()) 303 } else { 304 require.NoError(t, err) 305 require.Equal(t, fixAppInputBySystem(t, test.system), *regIn) 306 } 307 }) 308 } 309 }