github.com/mmatczuk/gohan@v0.0.0-20170206152520-30e45d9bdb69/extension/otto/gohan_resource_management.go (about) 1 // 2 // Copyright (C) 2015 NTT Innovation Institute, Inc. 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 // implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 package otto 17 18 import ( 19 "fmt" 20 21 "github.com/robertkrimen/otto" 22 23 "github.com/cloudwan/gohan/extension" 24 "github.com/cloudwan/gohan/schema" 25 "github.com/cloudwan/gohan/server/resources" 26 ) 27 28 const ( 29 noEnvironmentForSchemaErrorMessageFormat = "No environment for schema '%s'" 30 wrongResponseErrorMessageFormat = "Wrong response from %s" 31 notADictionaryErrorMessageFormat = "Not a dictionary: '%v'" 32 ) 33 34 func handleChainError(env *Environment, call *otto.FunctionCall, err error) { 35 switch err := err.(type) { 36 default: 37 ThrowOttoException(call, err.Error()) 38 case resources.ResourceError: 39 throwOtto(call, "ResourceException", err.Message, err.Problem) 40 case extension.Error: 41 exceptionInfo, _ := env.VM.ToValue(err.ExceptionInfo) 42 throwOtto(call, "ExtensionException", err.Error(), exceptionInfo) 43 } 44 } 45 46 func init() { 47 gohanChainingInit := func(env *Environment) { 48 vm := env.VM 49 builtins := map[string]interface{}{ 50 "gohan_model_list": func(call otto.FunctionCall) otto.Value { 51 VerifyCallArguments(&call, "gohan_model_list", 3) 52 context, err := GetMap(call.Argument(0)) 53 if err != nil { 54 ThrowOttoException(&call, err.Error()) 55 } 56 schemaID, err := GetString(call.Argument(1)) 57 if err != nil { 58 ThrowOttoException(&call, err.Error()) 59 } 60 filterMap, err := GetMap(call.Argument(2)) 61 if err != nil { 62 ThrowOttoException(&call, err.Error()) 63 } 64 65 resources, err := GohanModelList(context, schemaID, filterMap) 66 if err != nil { 67 handleChainError(env, &call, err) 68 } 69 70 value, _ := vm.ToValue(resources) 71 return value 72 }, 73 "gohan_model_fetch": func(call otto.FunctionCall) otto.Value { 74 VerifyCallArguments(&call, "gohan_model_fetch", 4) 75 context, err := GetMap(call.Argument(0)) 76 if err != nil { 77 ThrowOttoException(&call, err.Error()) 78 } 79 schemaID, err := GetString(call.Argument(1)) 80 if err != nil { 81 ThrowOttoException(&call, err.Error()) 82 } 83 resourceID, err := GetString(call.Argument(2)) 84 if err != nil { 85 ThrowOttoException(&call, err.Error()) 86 } 87 tenantIDs, err := GetStringList(call.Argument(3)) 88 if err != nil { 89 tenantIDs = nil 90 } 91 92 resource, err := GohanModelFetch(context, schemaID, resourceID, tenantIDs) 93 if err != nil { 94 handleChainError(env, &call, err) 95 } 96 97 value, _ := vm.ToValue(resource) 98 return value 99 }, 100 "gohan_model_create": func(call otto.FunctionCall) otto.Value { 101 VerifyCallArguments(&call, "gohan_model_create", 3) 102 context, err := GetMap(call.Argument(0)) 103 if err != nil { 104 ThrowOttoException(&call, err.Error()) 105 } 106 schemaID, err := GetString(call.Argument(1)) 107 if err != nil { 108 ThrowOttoException(&call, err.Error()) 109 } 110 dataMap, err := GetMap(call.Argument(2)) 111 if err != nil { 112 ThrowOttoException(&call, err.Error()) 113 } 114 115 resource, err := GohanModelCreate(context, schemaID, dataMap) 116 if err != nil { 117 handleChainError(env, &call, err) 118 } 119 120 value, _ := vm.ToValue(resource) 121 return value 122 }, 123 "gohan_model_update": func(call otto.FunctionCall) otto.Value { 124 VerifyCallArguments(&call, "gohan_model_update", 5) 125 context, err := GetMap(call.Argument(0)) 126 if err != nil { 127 ThrowOttoException(&call, err.Error()) 128 } 129 schemaID, err := GetString(call.Argument(1)) 130 if err != nil { 131 ThrowOttoException(&call, err.Error()) 132 } 133 resourceID, err := GetString(call.Argument(2)) 134 if err != nil { 135 ThrowOttoException(&call, err.Error()) 136 } 137 dataMap, err := GetMap(call.Argument(3)) 138 if err != nil { 139 ThrowOttoException(&call, err.Error()) 140 } 141 tenantIDs, err := GetStringList(call.Argument(4)) 142 if err != nil { 143 tenantIDs = nil 144 } 145 146 resource, err := GohanModelUpdate(context, schemaID, resourceID, dataMap, tenantIDs) 147 if err != nil { 148 handleChainError(env, &call, err) 149 } 150 151 value, _ := vm.ToValue(resource) 152 return value 153 }, 154 "gohan_model_delete": func(call otto.FunctionCall) otto.Value { 155 VerifyCallArguments(&call, "gohan_model_delete", 3) 156 context, err := GetMap(call.Argument(0)) 157 if err != nil { 158 ThrowOttoException(&call, err.Error()) 159 } 160 schemaID, err := GetString(call.Argument(1)) 161 if err != nil { 162 ThrowOttoException(&call, err.Error()) 163 } 164 resourceID, err := GetString(call.Argument(2)) 165 if err != nil { 166 ThrowOttoException(&call, err.Error()) 167 } 168 169 err = GohanModelDelete(context, schemaID, resourceID) 170 if err != nil { 171 handleChainError(env, &call, err) 172 } 173 174 return otto.Value{} 175 }, 176 } 177 178 for name, object := range builtins { 179 vm.Set(name, object) 180 } 181 } 182 RegisterInit(gohanChainingInit) 183 } 184 185 //GohanModelList lists gohan resources and running extensions 186 func GohanModelList(context map[string]interface{}, schemaID string, 187 filterMap map[string]interface{}) (interface{}, error) { 188 189 currentSchema, err := getSchema(schemaID) 190 if err != nil { 191 return nil, err 192 } 193 context["schema"] = currentSchema 194 context["path"] = currentSchema.GetPluralURL() 195 196 filter := map[string]interface{}{} 197 for key, value := range filterMap { 198 switch value := value.(type) { 199 default: 200 return nil, fmt.Errorf("Filter not a string nor array of strings") 201 case string: 202 filter[key] = value 203 case []interface{}: 204 for _, val := range value { 205 v, ok := val.(string) 206 if !ok { 207 return nil, fmt.Errorf("Filter not a string nor array of strings") 208 } 209 filter[key] = v 210 } 211 case []string: 212 for _, val := range value { 213 filter[key] = val 214 } 215 216 } 217 } 218 219 if err := resources.GetResourcesInTransaction( 220 context, currentSchema, filter, nil); err != nil { 221 return nil, err 222 } 223 response, ok := context["response"].(map[string]interface{}) 224 if !ok { 225 return nil, fmt.Errorf("No response") 226 } 227 resources, ok := response[currentSchema.Plural] 228 if !ok { 229 return nil, fmt.Errorf(wrongResponseErrorMessageFormat, "GetMultipleResources.") 230 } 231 return resources, nil 232 } 233 234 //GohanModelFetch fetch gohan resource and running extensions 235 func GohanModelFetch(context map[string]interface{}, schemaID string, resourceID string, 236 tenantIDs []string) (interface{}, error) { 237 238 currentSchema, err := getSchema(schemaID) 239 if err != nil { 240 return nil, err 241 } 242 context["schema"] = currentSchema 243 context["path"] = currentSchema.GetPluralURL() 244 245 if err := resources.GetSingleResourceInTransaction( 246 context, currentSchema, resourceID, tenantIDs); err != nil { 247 return nil, err 248 } 249 response, ok := context["response"].(map[string]interface{}) 250 if !ok { 251 return nil, fmt.Errorf("No response") 252 } 253 return response[currentSchema.Singular], nil 254 } 255 256 //GohanModelCreate creates gohan resource and running extensions 257 func GohanModelCreate(context map[string]interface{}, schemaID string, 258 dataMap map[string]interface{}) (interface{}, error) { 259 260 currentSchema, err := getSchema(schemaID) 261 if err != nil { 262 return nil, err 263 } 264 context["schema"] = currentSchema 265 context["path"] = currentSchema.GetPluralURL() 266 267 manager := schema.GetManager() 268 resourceObj, err := manager.LoadResource(currentSchema.ID, dataMap) 269 if err != nil { 270 return nil, err 271 } 272 273 if err := resources.CreateResourceInTransaction( 274 context, resourceObj); err != nil { 275 return nil, err 276 } 277 response, ok := context["response"].(map[string]interface{}) 278 if !ok { 279 return nil, fmt.Errorf("No response") 280 } 281 return response[currentSchema.Singular], nil 282 } 283 284 //GohanModelUpdate updates gohan resource and running extensions 285 func GohanModelUpdate(context map[string]interface{}, schemaID string, resourceID string, dataMap map[string]interface{}, tenantIDs []string) (interface{}, error) { 286 287 currentSchema, err := getSchema(schemaID) 288 if err != nil { 289 return nil, err 290 } 291 context["schema"] = currentSchema 292 context["path"] = currentSchema.GetPluralURL() 293 294 err = resources.UpdateResourceInTransaction(context, currentSchema, resourceID, dataMap, tenantIDs) 295 if err != nil { 296 return nil, err 297 } 298 response, ok := context["response"].(map[string]interface{}) 299 if !ok { 300 return nil, fmt.Errorf("No response") 301 } 302 return response[currentSchema.Singular], nil 303 } 304 305 //GohanModelDelete deletes gohan resources and running extensions 306 func GohanModelDelete(context map[string]interface{}, schemaID string, resourceID string) error { 307 308 currentSchema, err := getSchema(schemaID) 309 if err != nil { 310 return err 311 } 312 context["schema"] = currentSchema 313 context["path"] = currentSchema.GetPluralURL() 314 315 return resources.DeleteResourceInTransaction(context, currentSchema, resourceID) 316 }