• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

silvermine / cloudformation-custom-resources / 25019493962

27 Apr 2026 09:04PM UTC coverage: 40.509% (+40.5%) from 0.0%
25019493962

Pull #28

github

web-flow
Merge 9ddd1f898 into 4b63a9df4
Pull Request #28: feat: migrate to Node 24 and AWS SDK v3 (#445426)

31 of 112 branches covered (27.68%)

Branch coverage included in aggregate %.

68 of 159 new or added lines in 6 files covered. (42.77%)

2 existing lines in 1 file now uncovered.

144 of 320 relevant lines covered (45.0%)

5.15 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.96
/src/BaseResource.js
1
'use strict';
2

3
var _ = require('underscore'),
4✔
4
    https = require('https'),
4✔
5
    Class = require('class.extend');
4✔
6

7
module.exports = Class.extend({
4✔
8

9
   init: function(evt) {
10
      this._event = evt;
164✔
11
   },
12

13
   handleCreate: function() {
14
      var props = this.normalizeResourceProperties(this._event.ResourceProperties, true);
8✔
15

16
      console.log('handling creation of "%s": %j', this._event.LogicalResourceId, this._event.ResourceProperties);
8✔
17

18
      return this.doCreate(props)
8✔
19
         .then(this.respond.bind(this))
20
         .catch(this.sendError.bind(this));
21
   },
22

23
   handleUpdate: function() {
24
      var resourceID = this._event.PhysicalResourceId,
4✔
25
          props = this.normalizeResourceProperties(this._event.ResourceProperties, true),
4✔
26
          oldProps = this.normalizeResourceProperties(this._event.OldResourceProperties);
4✔
27

28
      console.log('handling update of "%s" (%s): %j', this._event.LogicalResourceId, resourceID, props);
4✔
29

30
      return this.doUpdate(resourceID, props, oldProps)
4✔
31
         .then(this.respond.bind(this))
32
         .catch(this.sendError.bind(this));
33
   },
34

35
   handleDelete: function() {
36
      var resourceID = this._event.PhysicalResourceId,
4✔
37
          props = this.normalizeResourceProperties(this._event.ResourceProperties, false);
4✔
38

39
      console.log('handling delete of "%s" (%s): %j', this._event.LogicalResourceId, resourceID, props);
4✔
40

41
      return this.doDelete(resourceID, props)
4✔
42
         .then(this.respond.bind(this))
43
         .catch(this.sendError.bind(this));
44
   },
45

46
   doCreate: function() {
47
      return Promise.resolve({});
8✔
48
   },
49

50
   doUpdate: function() {
51
      return Promise.resolve({});
8✔
52
   },
53

54
   doDelete: function() {
55
      return Promise.resolve({});
12✔
56
   },
57

58
   normalizeResourceProperties: function(props) {
59
      return props;
24✔
60
   },
61

62
   /**
63
    * See http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/crpg-ref-responses.html
64
    */
65
   respond: function(atts) {
66
      var resp = this._createResponse('SUCCESS', atts.PhysicalResourceId, _.omit(atts, 'PhysicalResourceId'));
12✔
67

68
      return this._sendResponse(resp);
12✔
69
   },
70

71
   _randomResourceID: function() {
72
      return `${this._event.LogicalResourceId}-${Math.random().toString(36).replace(/[^a-z]+/g, '')}`;
4✔
73
   },
74

75
   sendError: function(err) {
76
      var resp = this._createResponse('FAILED', null, null, err.message);
12✔
77

78
      console.log('ERROR:', err, err.stack);
12✔
79

80
      return this._sendResponse(resp);
12✔
81
   },
82

83
   _createResponse: function(status, resourceID, data, reason) {
84
      return {
44✔
85
         StackId: this._event.StackId,
86
         RequestId: this._event.RequestId,
87
         LogicalResourceId: this._event.LogicalResourceId,
88
         PhysicalResourceId: resourceID || this._event.PhysicalResourceId || this._randomResourceID(),
80✔
89
         Status: status,
90
         Reason: reason || undefined,
76✔
91
         Data: data,
92
      };
93
   },
94

95
   _sendResponse: function(resp) {
96
      var body = JSON.stringify(resp),
32✔
97
          parsedURL = new URL(this._event.ResponseURL),
32✔
98
          opts;
99

100
      console.log('Sending response to S3:', body);
32✔
101

102
      opts = {
32✔
103
         hostname: parsedURL.hostname,
104
         port: 443,
105
         path: parsedURL.pathname + parsedURL.search,
106
         method: 'PUT',
107
         headers: {
108
            'Content-Type': '',
109
            'Content-Length': body.length,
110
         },
111
      };
112

113
      return new Promise(function(resolve, reject) {
32✔
114
         var req;
115

116
         req = https.request(opts, function(response) {
32✔
117
            console.log('PUT response status:', response.statusCode);
28✔
118
            console.log('PUT response headers:', JSON.stringify(response.headers));
28✔
119
            resolve(resp);
28✔
120
         });
121

122
         req.on('error', function(err) {
32✔
123
            console.log('ERROR sending PUT request', err, err.stack);
4✔
124
            reject(err);
4✔
125
         });
126

127
         req.on('end', function() {
32✔
NEW
128
            console.log('end request');
×
129
         });
130

131
         req.write(body);
32✔
132
         req.end();
32✔
133
      });
134
   },
135

136
});
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc