Parsing integers in serverless.yml to use MemoryDB's ClusterEndpoint.Port in Environment Variable - aws-cloudformation

I'm creating a MemoryDB cluster for my serverless function, but the Port for the MemoryDB endpoint is an Integer, so when I try to set an environment variable to pass the endpoint URL to my function I get an error
Error:
Cannot resolve serverless.yml: Variables resolution errored with:
- Cannot resolve variable at "provider.environment.MEMORYDB_ENDPOINT": String value consist of variable which resolve with non-string value
Example serverless.yml file:
provider:
name: aws
# [...]
environment:
MEMORYDB_PORT: ${self:custom.MEMORYDB_PORT}
# [...]
custom:
MEMORYDB_PORT: !GetAtt MemoryDB.ClusterEndpoint.Port
I've tried with Fn::Join, Fn::Sub (plugin) and others but they all expect strings as arguments.
I'm not planning on using a custom port so I can always assume the default, however I feel like I'm missing some thing here.
Is there a way to parse integers in serverless/cloudformation somehow? Or at least convert that port into a string?

As far as I know serverless doesn't allow having functions in .yaml file, since that is just a declaration.
You could have a custom plugin: https://www.serverless.com/framework/docs/guides/plugins/custom-variables
It would looks something similar
export class MaxBatchingWindowIntParser {
public configurationVariablesSources: object;
public constructor() {
this.configurationVariablesSources = {
parseValue: {
resolve({ address }) {
return {
value: Number.parseInt(address, 10),
};
},
},
};
}
}

Related

What does the "\" notation do in the following Swift code snippet? [duplicate]

I'm new to backend Swift and thought I'd use Vapor to get up-and-running on a side project fast...
I ran vapor new WebServer --template=auth-template, and now I'm trying to figure out what something like return \.email means.
For more context, I'm looking in WebServer > Sources > App > Models > Users.swift:
import Authentication
import FluentSQLite
import Vapor
/// Allows users to be verified by basic / password auth middleware.
extension User: PasswordAuthenticatable {
/// See `PasswordAuthenticatable`.
static var usernameKey: WritableKeyPath<User, String> {
return \.email
}
// ...
}
And here is the definition of the User class:
/// A registered user, capable of owning todo items.
final class User: SQLiteModel {
// {omit extra code} ...
var email: String
// {omit extra code} ...
/// Creates a new `User`.
init(id: Int? = nil, name: String, email: String, passwordHash: String) {
// {omit extra code} ...
self.email = email
// {omit extra code} ...
}
}
What does this backslash-dot notation mean?
tl;dr: We take a look at the Swift language reference, and sure enough, the usage of this backslash-dot notation is called a key-path-expression.
(The question has been sufficiently answered, by this point.)
A more hands-on approach on how to get to that piece of buried documentation:
As you can see from the code you posted, the User class contains a property named email.
Notice that, assuming you're using Xcode, if you replace return \.email with return \, you get the compile-error "Expected expression path in Swift key path", so this is a hint that this backslash-dot notation might have to do with something called a key path.
From that documentation on key-path, we see that we could also have written \User.email (and you can try it out in Xcode with no compiler error).
Understanding the greater context of what's going on in that code:
So, semantically, to understand the meaning of the usernameKey declaration you're looking at, we might want to understand what a WritableKeyPath is. In simple, from the documentation, we see that a WritableKeyPath is: "A key path that supports reading from and writing to the resulting value."
So, we see that the usernameKey declaration takes in a WritableKeyPath object and returns a String that is User.email.
Furthermore, it's apparent that the User class needs this usernameKey property in order to conform to the PasswordAuthenticatable protocol, which was imported on the first line with import Authentication (if you care to explore there, take a look at Dependencies > Auth 2.0.0 > Authentication > Basic > BasicAuthenticatable.swift).

How to get filename for a class in Swift?

I have access to a Class ("AnyClass") object, and would like to get the file name for this class.
Tried searching online but couldn't find it anywhere. Is this possible in Swift?
EDIT: My use case (described in a comment below)
I'm collecting unit test metadata and mapping test ownership via .github/CODEOWNERS file. However, at runtime, unit test hooks (XCTestObservation) only has access to the class name of the test that is running, and the class name does not map to CODEOWNERS in any way. I would be able to map my repo's CODEOWNERS to the tests much easier if I just had the full path of the file that the unit test is running for.
protocol NameObject {
var className: String { get }
static var className: String { get } }
extension NameObject {
var className: String {
return String(describing: type(of: self))
}
static var className: String {
return String(describing: self)
}}
extension NSObject : NameObject {}
Copy and paste above code and then on any class just use YourViewController.className / YourView.className
The answer from #Rishabh Shukla gave me an idea for a possible approach, though its not straightforward and requires jumping through a few hoops.
So the idea would be to create a protocol :
protocol FileNameProvider {
var filename: StaticString { get }
}
And then leverage Sourcery - it will allow you to generate implementation for this protocol for each type. I think that the inline code generation approach would be best here, so your template would look something like this :
// in template:
{% for type in types.all %}
// sourcery:inline:{{ type.name }}.TemplateName
extension {{ type.name }}: FileNameProvider {
var filename: StaticString { return #file }
}
// sourcery:end
{% endfor %}
// in source code:
class MyType {
}
// sourcery:inline:MyType.TemplateName
// it should generate the code here
// sourcery:end
The downside of this is that you would need to manually (or via another script 🤔) add
// sourcery:inline:MyType.TemplateName
// sourcery:end
for each type in your codebase, which could be a lot.
Sourcery has the ability for automatic inlining, but apparently it has some problems at the moment when there are multiple types defined in a file and it seems from the docs that it adds the code at the end of the type, so it won't be possible to add protocol conformance this way as an extension.
So while this approach would save you from adding the inline annotations manually, it seems it's not feasible at this moment - or maybe it just requires more creative tinkering with the templates - like adding the implementation inline, but creating the empty extension declaration in a separate file from another Sourcery template 🤔.
The end goal of all of this would be to then use it as simply as
(object as? FileNameProvider)?.filename // if `object` type is Any/AnyObject
object.filename // if `object` type is directly from your codebase
Disclaimer : I was not able to test this approach at the moment of writing this, so your mileage may vary.

AWS-CDK Appsync Codefirst input types

To avoid duplication of data structures I wanted to reuse a type definition on an input type like this
export const DeviceStatus = new ObjectType('DeviceStatus', {
definition: {
time: timestamp,
firmwareVersion: string
},
});
export const DeviceStatusInput = new InputType('DeviceStatusInput', {
definition: {
tenantId: id_required,
deviceId: id_required,
// Reuse of DeviceStatus Field definition
status: DeviceStatus.attribute()
}
});
There is no error since the return type of DeviceStatus.attribute() is fine, and this works for ObjectType inheritance.
From my perspective this should work, but deploying results in a nasty "Internal Error creating Schema" error.
Of course I could move the whole definition into an object and reuse it but that seems weird. Is there any good solution on this for the CodeFirst approach
It seem to be invalid to reference object type in input type.
I recommend to view Can you make a graphql type both an input and output type?
Probably best you can do is to create some convenience method which will create you both object and input type from single definition.

Use same method to get env vironment in flutter from build command than from .env file

I am using this package to set environment variables in flutter in a .env .
To read the variables I have to have this is my main.dart
Future main() async {
await DotEnv().load('.env');
runApp(MyApp());
}
And then read like this
print(DotEnv().env['VAR_NAME']);
From this question, I can also add variables in the build command like this
flutter run --dart-define=APP_VERSION=0.1.2
And then to read the ones set in the build command, I have to do this
const appVersion = String.fromEnvironment('APP_VERSION', defaultValue: 'development');
Is there please a way that I can read variables set in either the .env file or the build command the same way?
I will have the variables in my .env file for local development, and the in dev and prod environments they will be set via commands. So how can I find a way that works for both cases?
Thank you
I am not familiar with the package you mentioned, but a fairly safe bet would be as follows:
Create a singleton class that is responsible for handling environment variables:
final env = Env._();
class Env {
Env._(); // private constructor to prevent accidental initialization
}
Create a method that gets an environment variable from its string, and choose something to default to. IMO I would give precedence to command line args, but that is a matter of taste:
String get(String key, {String defaultValue}) {
final fromFile = DotEnv().env[key];
final fromArgs = String.fromEnvironment(key);
// return the value from command line if it exists
// if not, return the value from .env file
// if still null, return a default
return fromArgs ?? fromFile ?? defaultValue;
}
You can then access the data globally using:
env.get('MY_VARIABLE_NAME', defaultValue: 'hello');
For even more brevity, you can use Dart's callable classes, by renaming get() to call(), and then consume it using:
env('MY_VARIABLE_NAME', defaultValue: 'hello');

How do I use Hasura/postgres uuid with apollo-ios and swift

I have a table defined in Hasura (Postgres) using native uuid as the field datatype. My goal is to create an update mutation from Swift but the uuid type is not mapped implicitly from Postgres through Hasura and Apollo to Swift. The Hasura documentation states that the uuid type supports using String but when I define the variables, in the update mutation, as a String!,
mutation RedeemMagicLinkCode($code: String!, $iosIdentifierForVendor: String!) {
__typename
update_entityname(where: {code: {_eq: $code}, iosIdentifierForVendor: {_is_null: true}}, _set: {iosIdentifierForVendor: $iosIdentifierForVendor}) {
returning {
id
}
}
}
I get an error from the Apollo code gen build step that Variable "$code" of type "String!" used in position expecting type "uuid".. When I change that to uuid!,
mutation RedeemMagicLinkCode($code: uuid!, $iosIdentifierForVendor: uuid!) {
__typename
update_en...
The code gen step completes, producing API.swift, but several instances of the compile error Use of undeclared type 'uuid' raise and are now coming from a failure during compile of the Apollo generated API.swift.
/// API.swift
...
public let operationName = "RedeemMagicLinkCode"
public var code: uuid
public var iosIdentifierForVendor: uuid
...
Can someone point me in the right direction for letting Swift know what a uuid is or defining my query so that I can pass a String as a parameter through the Apollo managed mutation? Thanks so much!
OM(Goodness), I might need to blush at how simple this solution was.
I considered the error Use of undeclared type 'uuid' plus the documentation that Hasura will accept a String for this custom scalar...
/// API+typealias.swift
public typealias uuid = String
I placed the above type alias code in a file all by itself in the folder where my GraphQL files are and voila, it worked great!
I'm not thrilled with this public type alias now hanging out at the global scope but I am thrilled with a working data service