Container has no mapping for port undefined and protocol tcp. Did you call "container.addPortMappings()"? - aws-cdk

I'm working on a CDK deployment of a DNS server using a pair of FargateServices behind a NetworkLoadBalancer. Since Fargate can't expose the same port as both TCP and UDP, this requires two separate services, one for tcp/53 and one for udp/53.
Defining and deploying the TCP service works just fine:
const taskDefTCP = new TaskDefinition(this, 'TaskDefTCP', {
compatibility: Compatibility.FARGATE,
cpu: '256',
memoryMiB: '512',
});
taskDefTCP.addToTaskRolePolicy(new PolicyStatement({
actions: [
'ssmmessages:CreateControlChannel',
'ssmmessages:CreateDataChannel',
'ssmmessages:OpenControlChannel',
'ssmmessages:OpenDataChannel'
],
resources: ['*'],
}));
taskDefTCP.taskRole.addManagedPolicy(ManagedPolicy.fromAwsManagedPolicyName('AmazonSSMManagedInstanceCore'));
const containerTCP = taskDefTCP.addContainer('ContainerTCP', {
image: ContainerImage.fromEcrRepository(repository),
portMappings: [{
containerPort: 53,
hostPort: 53,
protocol: ecsProtocol.TCP,
}],
environment: {
"AWS_ENVIRONMENT": 'DEV',
},
logging: LogDrivers.awsLogs({
logGroup: assets.dnsLogGroup,
streamPrefix: 'dns',
})
});
this.serviceSecurityGroup = new SecurityGroup(this, 'ServiceSecurityGroup', {
vpc: assets.vpc,
allowAllOutbound: true, // TODO: Lock this down.
});
this.serviceSecurityGroup.addIngressRule(Peer.anyIpv4(), Port.tcp(53), "TCP Queries");
this.serviceSecurityGroup.addIngressRule(Peer.anyIpv4(), Port.udp(53), "UDP Queries");
this.dnsServiceTCP = new FargateService(this, 'ServiceTCP', {
cluster: cluster,
enableExecuteCommand: true,
assignPublicIp: false,
taskDefinition: taskDefTCP,
securityGroups: [this.serviceSecurityGroup],
vpcSubnets: {
subnets: assets.mycorpNetworkResources.getSubnets(NetworkEnvironment.DEV, SubnetType.DNS),
}
});
const autoScaleTCP = this.dnsServiceTCP.autoScaleTaskCount({maxCapacity: 2, minCapacity: 1});
If I add the same code copy/pasted from the code above that works, just with TCP changed to UDP, I get an error:
Container 'AuthDNSApplicationStack/TaskDefUDP/ContainerUDP' has no mapping for port undefined and protocol tcp. Did you call "container.addPortMappings()"?
Of course it has no mapping for TCP. It's a UDP container! Here's the code that, when added, produces the above error:
const taskDefUDP = new TaskDefinition(this, 'TaskDefUDP', {
compatibility: Compatibility.FARGATE,
cpu: '256',
memoryMiB: '512',
});
taskDefUDP.addToTaskRolePolicy(new PolicyStatement({
actions: [
'ssmmessages:CreateControlChannel',
'ssmmessages:CreateDataChannel',
'ssmmessages:OpenControlChannel',
'ssmmessages:OpenDataChannel'
],
resources: ['*'],
}));
taskDefUDP.taskRole.addManagedPolicy(ManagedPolicy.fromAwsManagedPolicyName('AmazonSSMManagedInstanceCore'));
const containerUDP = taskDefUDP.addContainer('ContainerUDP', {
image: ContainerImage.fromEcrRepository(repository),
portMappings: [{
containerPort: 53,
hostPort: 53,
protocol: ecsProtocol.UDP,
}],
environment: {
"AWS_ENVIRONMENT": 'DEV',
},
logging: LogDrivers.awsLogs({
logGroup: assets.dnsLogGroup,
streamPrefix: 'dns',
})
});
this.dnsServiceUDP = new FargateService(this, 'ServiceUDP', {
cluster: cluster,
enableExecuteCommand: true,
assignPublicIp: true,
taskDefinition: taskDefUDP,
securityGroups: [this.serviceSecurityGroup],
vpcSubnets: {
subnets: assets.mycorpNetworkResources.getSubnets(NetworkEnvironment.DEV, SubnetType.DNS),
}
});
const autoScaleUDP = this.dnsServiceUDP.autoScaleTaskCount({maxCapacity: 2, minCapacity: 1});
Anyone know where I'm going wrong here?

When adding the dnsServiceUDP service to the NLB with addTarget, explicitly pass protocol: elbv2.Protocol.UDP in the AddNetworkTargetsProps.
The target protocol defaults to TCP if not explicitly provided.

Related

Having problems to add SSL to nuxt-axios web app on DOCKER

Well after many tests and brain burns trying with nginx, caddy and other resources to apply SSL I resort to this medium.
all the services are running on docker container.
I can't fully apply the certificates, rather I can't get my site to work with SSL, I can get to the login with https but then I can't get past that barrier:
to formalize:
https://example.com:3000/login (basic web domain)
https://example.com:3001/api (all my resources)
for https i have to change the axios BASEurl form: (recomendations from caddy forum)
this: http://example.com:3001/api
to this: https://example.com/api
to stop having the error of ERR_SSL_PROTOCOL_ERROR
I share my settings from my last failed attempt with caddy.
The truth is that at this point I don't know if it is a bad configuration problem on the caddy side or on the node-nuxt-axios side.
caddyfile:
{
debug
}
example.com {
handle_path /api/* {
reverse_proxy /api/* node:3001
}
handle {
reverse_proxy node:3000
}
}
emqx.example.com {
reverse_proxy emqx:18083
}
ws.example.com {
reverse_proxy emqx:8083
}
wss.example.com {
reverse_proxy emqx:8084
}
portainer.example.com {
reverse_proxy portainer:9000
}
here it goes nuxt.config.js
axios: {
baseURL: process.env.AXIOS_BASE_URL
},
env: {
mqtt_prefix: process.env.MQTT_PREFIX,
mqtt_host: process.env.MQTT_HOST,
mqtt_port: process.env.MQTT_PORT
},
server: {
https: true,
port: 3000,
host: '0.0.0.0',
},
serverMiddleware: {
https: true,
'/api': '~/api'
},
here is the index.js for api
const express = require("express");
const mongoose = require("mongoose");
const morgan = require("morgan");
const cors = require("cors");
const colors = require("colors");
const app = express();
require("dotenv").config();
//express config
app.use(morgan("tiny"));
app.use(express.json());
app.use(express.urlencoded({
extended: true,
})
);
app.use(cors());
app.use("/api", require("./routes/devices.js"));
app.use("/api", require("./routes/users.js"));
app.use("/api", require("./routes/templates.js"));
app.use("/api", require("./routes/datas.js"));
app.use("/api", require("./routes/webhooks.js"));
app.use("/api", require("./routes/emqxapi.js"));
app.use("/api", require("./routes/alarms.js"));
app.use("/api", require("./routes/controls.js")); // nueva funcion
app.use("/api", require("./routes/dataprovider.js"));
module.exports = app;
//listener
app.listen(process.env.API_PORT, () => {
console.log("API server listening on port " + process.env.API_PORT);
}); //api port 3001
for the record all services works like a charm on http, but having problems with secure comunication.

How to use PM2 Process Manager with SvelteKit

I am trying to manage my SvelteKit build with PM2 (Process Manager) — my problem is that I can't succesfully inject a .env-file using an ecosystem.config.cjs. My files currently look like this:
.env.production
PORT=3000
The only changing thing in both configs is at:
env: { }
ecosystem.config.cjs (working fine - app runs on provided port)
module.exports = {
apps: [
{
name: 'my_app',
script: './build/index.js',
watch: false,
ignore_watch: ['database'],
autorestart: true,
// --------------------------------------------------
// if passed directly PORT is being used as expected:
// --------------------------------------------------
env: {
PORT: 3000
}
}
]
};
ecosystem.config.cjs (not working - injected PORT variable is being ignored)
module.exports = {
apps: [
{
name: 'my_app',
script: './build/index.js',
watch: false,
ignore_watch: ['database'],
autorestart: true,
// ----------------------------------------------------
// when I try to inject a .env it's just being ignored:
// ----------------------------------------------------
env: {
ENV_PATH: "./.env.production",
}
}
]
};
Any help is much appreciated and thanks for reading!
Cheers,
Boris
EDIT: Made question a bit more clear + added answer below
The problem wasn't the injection of .env.production, but the PORT environment variable. PORT must be provided directly and can't be part of .env.production (well, it can be but will be ignored).
There's probably another way, but the following works:
ecosystem.config.cjs
module.exports = {
apps: [
{
name: 'my_app',
script: './build/index.js',
watch: false,
ignore_watch: ['database'],
autorestart: true,
// ----------------------------------------------------
// when I try to inject a .env it's just being ignored:
// ----------------------------------------------------
env: {
PORT: 3000,
ENV_PATH: "./.env.production",
}
}
]
};
.env.production
# production
PUBLIC_test=value

How Can I Reference Environment Variables in serverless.ts?

I'm using serverless-ssm-fetch in my serverless.ts file, which resolves many of the variables that are environment specific. This works great when I'm referencing these variables in my code, however, I have two values in my serverless.ts file itself that I'd like to draw from SSM Parameter Store. Below is my serverless.ts file, and what I'm trying to do to pull in lambda-security-group-ids and lambda-subnet-ids is working, but I'm not sure how to reference them within the serverless.ts file. Does anyone know how to do this?
import type { AWS } from '#serverless/typescript';
import importFacility from '#functions/ImportFacility';
import ProcessEvent from '#functions/ProcessEvent';
const serverlessConfiguration: AWS = {
service: 'myservice',
frameworkVersion: '2',
custom: {
webpack: {
webpackConfig: './webpack.config.js',
includeModules: true,
},
bundle: {
ignorePackages: ['pg-native']
},
serverlessSsmFetch: {
DB_Host: 'database-host~true',
PORT: 'serverless-database-port~true',
DB_NAME: 'clinical-database-name~true',
DB_USER_NAME: 'database-username~true',
DB_PASSWORD: 'database-password~true',
AWS_ACCESS_KEY: 'serverless-access-key-id~true',
AWS_SECRECT_KEY: 'serverless-access-key-secret~true',
LAMBDA_SECURITY_GROUP_IDS: 'lambda-security-group-ids~true', // WANT TO REFERENCE
LAMBDA_SUBNET_IDS: 'lambda-subnet-ids~true' // WANT TO REFERENCE
}
},
plugins: ['serverless-webpack', 'serverless-ssm-fetch'],
provider: {
name: 'aws',
runtime: 'nodejs14.x',
apiGateway: {
minimumCompressionSize: 1024,
shouldStartNameWithService: true,
},
environment: {
AWS_NODEJS_CONNECTION_REUSE_ENABLED: '1'
},
lambdaHashingVersion: '20201221',
vpc: {
securityGroupIds: [`${process.env.LAMBDA_SECURITY_GROUP_IDS}`], // NOT WORKING
subnetIds: [`${process.env.LAMBDA_SUBNET_IDS}`] // NOT WORKING
}
},
functions: { importFacility, ProcessEvent },
};
module.exports = serverlessConfiguration;
For anyone wondering juste had the issue
the syntax :
vpc: {
securityGroupIds: ['${ssm:${self:custom.serverlessSsmFetch.LAMBDA_SECURITY_GROUP_IDS}}'],
subnetIds: ['${ssm:${self:custom.serverlessSsmFetch.LAMBDA_SUBNET_IDS}}]
}
worked for me.
As far as I understand you have to use the syntax as it would have been rendered while using serverless.yml template

Executing WDIO-Test locally in a docker container throws error: #wdio/cli:utils: A service failed in the 'onPrepare' hook

I'm executing a headless e2e-test locally in a docker-container like so:
docker-compose up
yarn test
I get this error-message at the beginning:
ERROR #wdio/cli:utils: A service failed in the 'onPrepare' hook
TypeError: Cannot read property 'args' of undefined
at DockerLauncher.onPrepare (C:\myProgs\myWDIOTest\node_modules\wdio-docker-service\lib\launcher.js:30:9)
at C:\myWDIOTest\myWDIOTest\node_modules\#wdio\cli\build\utils.js:24:40
at Array.map (<anonymous>)
at Object.runServiceHook (C:\myProgs\myWDIOTest\node_modules\#wdio\cli\build\utils.js:21:33)
at Launcher.run (C:\myProgs\myWDIOTest\node_modules\#wdio\cli\build\launcher.js:61:27)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
I'm not using the onPrepare-Hook the wdio-configuration-file (see below).
The test carries on and actually finishes successfully every time, just like it's supposed to. At this point simply suppressing this error-message would be a viable solution for me (since this error doesn't compromise the test-results).
There exists a solution here for tests run on saucelabs, however that won't work for me. But this makes me wonder if I have to look for the solution in my docker-compose-file:
version: "3"
services:
chrome:
image: selenium/node-chrome:4.0.0-rc-1-prerelease-20210713
shm_size: 2gb
depends_on:
- selenium-hub
environment:
- SE_EVENT_BUS_HOST=selenium-hub
- SE_EVENT_BUS_PUBLISH_PORT=4442
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
ports:
- "6900:5900"
selenium-hub:
image: selenium/hub:4.0.0-rc-1-prerelease-20210713
container_name: selenium-hub
ports:
- "4442:4442"
- "4443:4443"
- "4444:4444"
This is the contents of my wdio-configuration-file:
import BrowserOptions from "./browserOpts";
import CucumberOptions from "./cucumberOpts";
const fs = require('fs');
const wdioParallel = require('wdio-cucumber-parallel-execution');
const reporter = require('cucumber-html-reporter');
const currentTime = new Date().toJSON().replace(/:/g, "-");
const jsonTmpDirectory = `reports/json/tmp/`;
let featureFilePath = `featureFiles/*.feature`;
let timeout = 30000;
exports.config = {
hostname: 'localhost',
port: 4444,
sync: true,
specs: [
featureFilePath
],
maxInstances: 1,
capabilities: [{
maxInstances: 1,
browserName: "chrome",
'goog:chromeOptions': BrowserOptions.getChromeOpts(),
}],
logLevel: 'error',
bail: 0,
baseUrl: 'http://localhost',
waitforTimeout: timeout,
connectionRetryTimeout: timeout * 3,
connectionRetryCount: 3,
services: ['docker'],
framework: 'cucumber',
reporters: [
['cucumberjs-json', {
jsonFolder: jsonTmpDirectory,
language: 'de'
}]
],
cucumberOpts: CucumberOptions.getDefaultSettings(),
before: function (capabilities, specs) {
browser._setWindowSize(1024, 768)
},
beforeSuite: function (suite) {
console.log(`Suite "${suite.fullTitle}" from file "${suite.file}" starts`);
},
beforeTest: function (test) {
console.log(`Test "${test.title}" starts`);
},
afterTest: function (test) {
console.log(`Test "${test.title}" finished`);
},
onComplete: () => {
console.log('<<< E2E-TEST COMPLETED >>>\n\n');
try {
let consolidatedJsonArray = wdioParallel.getConsolidatedData({
parallelExecutionReportDirectory: jsonTmpDirectory
});
let jsonFile = `${jsonTmpDirectory}report.json`;
fs.writeFileSync(jsonFile, JSON.stringify(consolidatedJsonArray));
let options = {
theme: 'bootstrap',
jsonFile: jsonFile,
output: `reports/html/report-${currentTime}.html`,
reportSuiteAsScenarios: true,
scenarioTimestamp: true,
launchReport: true,
ignoreBadJsonFile: true
};
reporter.generate(options);
} catch (err) {
console.log('err', err);
}
}
};
Your docker-compose.yml should work with Webdriverio if you remove services: ['docker'], from wdio.conf.js.
Based on a comment in this video, services: ['docker'] is needed if you want wdio to instantiate it's own containers.
To get rid of this error message specify separate configuration file for wdio docker and leave services with empty array - for me it worked and wdio knows that it should run tests on the container, hope it helped
services: [],

Grunt Livereload + Grunt Connect Proxy

I am using Rails for my API, AngularJS on the front and I am having some issues getting livereload / grunt connect proxy to work properly.
Here is the snippet from my gruntfile:
connect: {
options: {
port: 9000,
// Change this to '0.0.0.0' to access the server from outside.
hostname: 'localhost',
livereload: 35729
},
proxies: [
{
context: '/api',
host: 'localhost',
port: 3000
}
],
livereload: {
options: {
open: true,
base: [
'.tmp',
'<%= yeoman.app %>'
],
middleware: function (connect, options) {
var middlewares = [];
var directory = options.directory || options.base[options.base.length - 1];
// enable Angular's HTML5 mode
middlewares.push(modRewrite(['!\\.html|\\.js|\\.svg|\\.css|\\.png$ /index.html [L]']));
if (!Array.isArray(options.base)) {
options.base = [options.base];
}
options.base.forEach(function(base) {
// Serve static files.
middlewares.push(connect.static(base));
});
// Make directory browse-able.
middlewares.push(connect.directory(directory));
return middlewares;
}
}
},
test: {
options: {
port: 9001,
base: [
'.tmp',
'test',
'<%= yeoman.app %>'
]
}
},
dist: {
options: {
base: '<%= yeoman.dist %>'
}
}
}
If I 'grunt build' everything works perfectly - off localhost:3000
However if I 'grunt serve' it opens a window through 127.0.0.1:9000 and I get 404 to all my API calls.
Also under serve it is mangling my background images from a CSS file I get this warning:
Resource interpreted as Image but transferred with MIME type text/html: "http://127.0.0.1:9000/images/RBP_BG.jpg"
I haven't done this before - so chances are I am doing it all wrong.
I don't like too much code in your connect.livereload.middleware configuration.
Is that all necessary ?
Take a look at this commit - chore(yeoman-gruntfile-update): configured grunt-connect-proxy in some of my projects.
backend is Django
ports: frontend: 9000, backend: 8000
generator-angular was in v.0.6.0 when generating the project
my connect.livereload.middleware configuration was based on: https://stackoverflow.com/a/19403176/1432478
This is an old post, but please make sure that you actually initialize the proxy in the grunt serve task by calling configureProxies before livereload.
grunt.task.run([
'clean:server',
'bower-install',
'concurrent:server',
'autoprefixer',
'configureProxies',
'connect:livereload',
'watch'
]);
Should work fine afterwards.
I have a similar problem with you but I have no use yeoman.
My solution is to add the task 'configureProxies'.
this is my tasks:
grunt.registerTask('serve', ['connect:livereload','configureProxies',
'open:server', 'watch']);
and,'connect:livereload','configureProxies'——After my test, the order of these two tasks will not affect the results.
github grunt-connect-proxy

Resources