Terraform Automation Account install SqlServer PS Library - terraform-provider-azure

while trying to install a module in a automation account I’m getting a error
This is the code
resource "azurerm_automation_module" "mod_sqlserver" {
name = "xSqlServer"
resource_group_name = module.aut_resourcegroup.rg.name
automation_account_name = azurerm_automation_account.aut.name
module_link {
uri = "https://devopsgallerystorage.blob.core.windows.net/packages/sqlserver.21.1.18256.nupkg"
}
}
This is the error
│ Error: waiting for Module "xSqlServer" (Automation Account "aut-eu2-prd-edw-001" / Resource Group "rg-prd-edw-001") to finish provisioning: Orchestrator.Shared.AsyncModuleImport.ModuleImportException: Cannot import the module of name xSqlServer, as the module structure was invalid.
│ at Orchestrator.Activities.GetModuleMetadataAfterValidationActivity.ExecuteInternal(CodeActivityContext context, Byte[] moduleContent, String moduleName, ModuleLanguage moduleLanguage)
│ at Orchestrator.Activities.GetModuleMetadataAfterValidationActivity.Execute(CodeActivityContext context)
│ at System.Activities.CodeActivity.InternalExecute(ActivityInstance instance, ActivityExecutor executor, BookmarkManager bookmarkManager)
│ at System.Activities.Runtime.ActivityExecutor.ExecuteActivityWorkItem.ExecuteBody(ActivityExecutor executor, BookmarkManager bookmarkManager, Location resultLocation)
│
│ with module.provision_aut[0].module.aut_create["aut-01"].azurerm_automation_module.mod_sqlserver,
│ on _modules/general/aut/aut_create/main.tf line 57, in resource "azurerm_automation_module" "mod_sqlserver":
│ 57: resource "azurerm_automation_module" "mod_sqlserver" {
│
╵
##[error]Terraform command 'apply' failed with exit code '1'.
##[error]╷
│ Error: waiting for Module "xSqlServer" (Automation Account "aut-eu2-prd-edw-001" / Resource Group "rg-prd-edw-001") to finish provisioning: Orchestrator.Shared.AsyncModuleImport.ModuleImportException: Cannot import the module of name xSqlServer, as the module structure was invalid.
│ at Orchestrator.Activities.GetModuleMetadataAfterValidationActivity.ExecuteInternal(CodeActivityContext context, Byte[] moduleContent, String moduleName, ModuleLanguage moduleLanguage)
│ at Orchestrator.Activities.GetModuleMetadataAfterValidationActivity.Execute(CodeActivityContext context)
│ at System.Activities.CodeActivity.InternalExecute(ActivityInstance instance, ActivityExecutor executor, BookmarkManager bookmarkManager)
Any ideas on what’s wrong ?

I have tested in my environment.
I used the same code as above and got the below error :
As you are downloading the xSqlServer module not SqlServer module, you can use :
uri = "https://devopsgallerystorage.blob.core.windows.net/packages/xsqlserver.9.1.0.nupkg"
Instead of :
uri = "https://devopsgallerystorage.blob.core.windows.net/packages/sqlserver.21.1.18256.nupkg"
So the code should be :
resource "azurerm_automation_module" "mod_sqlserver" {
name = "xSqlServer"
resource_group_name = module.aut_resourcegroup.rg.name
automation_account_name = azurerm_automation_account.aut.name
module_link {
uri = "https://devopsgallerystorage.blob.core.windows.net/packages/xsqlserver.9.1.0.nupkg"
}
}
If you want to install SqlServer module, you can use the below code :
resource "azurerm_automation_module" "mod_sqlserver" {
name = "SqlServer"
resource_group_name = module.aut_resourcegroup.rg.name
automation_account_name = azurerm_automation_account.aut.name
module_link {
uri = "https://devopsgallerystorage.blob.core.windows.net/packages/sqlserver.21.1.18256.nupkg"
}
}

Related

Localstack Lambda Invoke fails on Windows

I have a problem similar to Unable to invoke lambda function from localstack via aws cli, but with a different symptom. The solution described in that SO does not work for me.
I am running on Windows 10, with the latest versions of Docker, Terraform and LocalStack (as of April/May 2021). All commands are typed into an Windows cmd window with Administrator permissions, set to the correct working folder.
I start local stack using docker-compose up -d, with the following docker-compose.yml
version: '3.2'
services:
localstack:
image: localstack/localstack-full:latest
container_name: localstack_serverless1
ports:
- '4566:4566'
- '8055:8080'
environment:
# - HOSTNAME_EXTERNAL=localstack
- COMPOSE_CONVERT_WINDOWS_PATHS=1
- DEBUG=1
- DATA_DIR=/tmp/localstack/data
- LAMBDA_EXECUTOR=docker
- START_WEB=1
#- DOCKER_HOST=unix:///var/run/docker.sock
volumes:
- './.localstack:/tmp/localstack'
- '/var/run/docker.sock:/var/run/docker.sock'
#- './docker.sock:/var/run/docker.sock'
The lines commented out are things I have tried that didn't make a difference.
I then run terraform init, and terraform apply, with the following input:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.27"
}
}
required_version = ">= 0.14.9"
}
provider "aws" {
access_key = "mock_access_key"
region = "us-east-1"
s3_force_path_style = true
secret_key = "mock_secret_key"
skip_credentials_validation = true
skip_metadata_api_check = true
skip_requesting_account_id = true
# AWS Provider version held back for this issue:
# https://github.com/localstack/localstack/issues/1818
# (localstack's fix not released yet)
# version = "2.39.0"
endpoints {
apigateway = "http://localhost:4566"
cloudformation = "http://localhost:4566"
cloudwatch = "http://localhost:4566"
dynamodb = "http://localhost:4566"
ec2 = "http://localhost:4566"
es = "http://localhost:4566"
firehose = "http://localhost:4566"
iam = "http://localhost:4566"
kinesis = "http://localhost:4566"
lambda = "http://localhost:4566"
route53 = "http://localhost:4566"
redshift = "http://localhost:4566"
s3 = "http://localhost:4566"
secretsmanager = "http://localhost:4566"
ses = "http://localhost:4566"
sns = "http://localhost:4566"
sqs = "http://localhost:4566"
ssm = "http://localhost:4566"
stepfunctions = "http://localhost:4566"
sts = "http://localhost:4566"
}
}
resource "aws_s3_bucket" "serverless1_bucket1" {
bucket = "serverless1-bucket1"
acl = "private"
}
resource "aws_s3_bucket_object" "upload_code_lambda1" {
bucket = "serverless1-bucket1"
key = "v1.0.0/lambda1.zip"
source = "lambda1.zip"
depends_on = [aws_s3_bucket.serverless1_bucket1]
}
resource "aws_lambda_function" "serverless1_lambda1" {
function_name = "serverless1-lambda1"
# The bucket name as created earlier with "aws s3api create-bucket"
s3_bucket = "serverless1-bucket1"
s3_key = "v1.0.0/lambda1.zip"
# "lambda1" is the filename within the zip file (lambda1.js) and "handler"
# is the name of the property under which the handler function was
# exported in that file.
handler = "lambda1.handler"
runtime = "nodejs10.x"
role = aws_iam_role.lambda_exec.arn
# Ant Waters: I have added this to make lambda creation wait until the code has been uploaded. I'm not sure if it is needed or not.
depends_on = [aws_s3_bucket_object.upload_code_lambda1]
}
# IAM role which dictates what other AWS services the Lambda function
# may access.
resource "aws_iam_role" "lambda_exec" {
name = "serverless_example_lambda"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_api_gateway_rest_api" "example" {
name = "ServerlessExample1"
description = "Terraform Serverless Application Example"
}
resource "aws_api_gateway_resource" "proxy" {
rest_api_id = aws_api_gateway_rest_api.example.id
parent_id = aws_api_gateway_rest_api.example.root_resource_id
path_part = "{proxy+}"
}
resource "aws_api_gateway_method" "proxy" {
rest_api_id = aws_api_gateway_rest_api.example.id
resource_id = aws_api_gateway_resource.proxy.id
http_method = "ANY"
authorization = "NONE"
}
resource "aws_api_gateway_integration" "lambda" {
rest_api_id = aws_api_gateway_rest_api.example.id
resource_id = aws_api_gateway_method.proxy.resource_id
http_method = aws_api_gateway_method.proxy.http_method
integration_http_method = "POST"
type = "AWS_PROXY"
uri = aws_lambda_function.serverless1_lambda1.invoke_arn
}
resource "aws_api_gateway_method" "proxy_root" {
rest_api_id = aws_api_gateway_rest_api.example.id
resource_id = aws_api_gateway_rest_api.example.root_resource_id
http_method = "ANY"
authorization = "NONE"
}
resource "aws_api_gateway_integration" "lambda_root" {
rest_api_id = aws_api_gateway_rest_api.example.id
resource_id = aws_api_gateway_method.proxy_root.resource_id
http_method = aws_api_gateway_method.proxy_root.http_method
integration_http_method = "POST"
type = "AWS_PROXY"
uri = aws_lambda_function.serverless1_lambda1.invoke_arn
}
resource "aws_api_gateway_deployment" "example" {
depends_on = [
aws_api_gateway_integration.lambda,
aws_api_gateway_integration.lambda_root,
]
rest_api_id = aws_api_gateway_rest_api.example.id
stage_name = "test"
}
resource "aws_lambda_permission" "apigw" {
statement_id = "AllowAPIGatewayInvoke"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.serverless1_lambda1.function_name
principal = "apigateway.amazonaws.com"
# The "/*/*" portion grants access from any method on any resource
# within the API Gateway REST API.
source_arn = "${aws_api_gateway_rest_api.example.execution_arn}/*/*"
}
output "base_url" {
value = aws_api_gateway_deployment.example.invoke_url
}
The gateway stuff is copied from a tutorial, and I don't understand it yet.
I can then see the lambda in "https://app.localstack.cloud/resources" and "https://app.localstack.cloud/resources/gateway", and there is an Invoke button on the gateway page.
However, when I press this nothing seems to happen, except an error log in CloudWatch:
Similarly, I can see the function using the AWS CLI, with the call:
aws lambda get-function --function-name "serverless1-lambda1" --endpoint-url=http://localhost:4566
which returns:
{
"Configuration": {
"FunctionName": "serverless1-lambda1",
"FunctionArn": "arn:aws:lambda:us-east-1:000000000000:function:serverless1-lambda1",
"Runtime": "nodejs10.x",
"Role": "arn:aws:iam::000000000000:role/serverless_example_lambda",
"Handler": "lambda1.handler",
"CodeSize": 342,
"Description": "",
"Timeout": 3,
"MemorySize": 128,
"LastModified": "2021-05-07T10:17:32.305+0000",
"CodeSha256": "qoP7ORF4AUC8VJWLR0bGGRRKGtNrQwRj2hCa1n+3wk4=",
"Version": "$LATEST",
"VpcConfig": {},
"TracingConfig": {
"Mode": "PassThrough"
},
"RevisionId": "ea163f0f-81ce-4b3a-a0d1-7b44379c6492",
"State": "Active",
"LastUpdateStatus": "Successful",
"PackageType": "Zip"
},
"Code": {
"Location": "http://localhost:4566/2015-03-31/functions/serverless1-lambda1/code"
},
"Tags": {}
}
However, when I try to invoke it using:
aws --endpoint-url=http://localhost:4566 lambda invoke --function-name "serverless1-lambda1" output.json
The return is:
{
"errorMessage": "Lambda process returned error status code: 1. Result: . Output:\nUnable to find image 'lambci/lambda:nodejs10.x' locally\nError response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)\nmust specify at least one container source\njson: cannot unmarshal array into Go value of type types.ContainerJSON",
"errorType": "InvocationException",
"stackTrace": [
" File \"/opt/code/localstack/localstack/services/awslambda/lambda_api.py\", line 602, in run_lambda\n result = LAMBDA_EXECUTOR.execute(func_arn, func_details, event, context=context,\n",
" File \"/opt/code/localstack/localstack/services/awslambda/lambda_executors.py\", line 176, in execute\n return do_execute()\n",
" File \"/opt/code/localstack/localstack/services/awslambda/lambda_executors.py\", line 168, in do_execute\n return _run(func_arn=func_arn)\n",
" File \"/opt/code/localstack/localstack/utils/cloudwatch/cloudwatch_util.py\", line 149, in wrapped\n raise e\n",
" File \"/opt/code/localstack/localstack/utils/cloudwatch/cloudwatch_util.py\", line 145, in wrapped\n result = func(*args, **kwargs)\n",
" File \"/opt/code/localstack/localstack/services/awslambda/lambda_executors.py\", line 159, in _run\n raise e\n",
" File \"/opt/code/localstack/localstack/services/awslambda/lambda_executors.py\", line 147, in _run\n result = self._execute(func_arn, func_details, event, context, version)\n",
" File \"/opt/code/localstack/localstack/services/awslambda/lambda_executors.py\", line 325, in _execute\n result = self.run_lambda_executor(cmd, stdin, env_vars=environment, func_details=func_details)\n",
" File \"/opt/code/localstack/localstack/services/awslambda/lambda_executors.py\", line 231, in run_lambda_executor\n raise InvocationException('Lambda process returned error status code: %s. Result: %s. Output:\\n%s' %\n"
]
}
and the Docker window trace shows:
localstack_serverless1 | 2021-05-07T10:59:50:WARNING:localstack.services.awslambda.lambda_executors: Empty event body specified for invocation of Lambda "arn:aws:lambda:us-east-1:000000000000:function:serverless1-lambda1"
localstack_serverless1 | 2021-05-07T10:59:50:INFO:localstack.services.awslambda.lambda_executors: Running lambda cmd: CONTAINER_ID="$(docker create -i -e AWS_REGION="$AWS_REGION" -e DOCKER_LAMBDA_USE_STDIN="$DOCKER_LAMBDA_USE_STDIN" -e LOCALSTACK_HOSTNAME="$LOCALSTACK_HOSTNAME" -e EDGE_PORT="$EDGE_PORT" -e _HANDLER="$_HANDLER" -e AWS_LAMBDA_FUNCTION_TIMEOUT="$AWS_LAMBDA_FUNCTION_TIMEOUT" -e AWS_LAMBDA_FUNCTION_NAME="$AWS_LAMBDA_FUNCTION_NAME" -e AWS_LAMBDA_FUNCTION_VERSION="$AWS_LAMBDA_FUNCTION_VERSION" -e AWS_LAMBDA_FUNCTION_INVOKED_ARN="$AWS_LAMBDA_FUNCTION_INVOKED_ARN" -e AWS_LAMBDA_COGNITO_IDENTITY="$AWS_LAMBDA_COGNITO_IDENTITY" -e NODE_TLS_REJECT_UNAUTHORIZED="$NODE_TLS_REJECT_UNAUTHORIZED" --rm "lambci/lambda:nodejs10.x" "lambda1.handler")";docker cp "/tmp/localstack/zipfile.9cb3ff88/." "$CONTAINER_ID:/var/task"; docker start -ai "$CONTAINER_ID";
localstack_serverless1 | 2021-05-07T11:00:05:DEBUG:localstack.services.awslambda.lambda_executors: Lambda arn:aws:lambda:us-east-1:000000000000:function:serverless1-lambda1 result / log output:
localstack_serverless1 |
localstack_serverless1 | > Unable to find image 'lambci/lambda:nodejs10.x' locally
localstack_serverless1 | > Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
localstack_serverless1 | > must specify at least one container source
localstack_serverless1 | > json: cannot unmarshal array into Go value of type types.ContainerJSON
localstack_serverless1 | 2021-05-07T11:00:05:INFO:localstack.services.awslambda.lambda_api: Error executing Lambda function arn:aws:lambda:us-east-1:000000000000:function:serverless1-lambda1: Lambda process returned error status code: 1. Result: . Output:
localstack_serverless1 | Unable to find image 'lambci/lambda:nodejs10.x' locally
localstack_serverless1 | Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
localstack_serverless1 | must specify at least one container source
localstack_serverless1 | json: cannot unmarshal array into Go value of type types.ContainerJSON Traceback (most recent call last):
localstack_serverless1 | File "/opt/code/localstack/localstack/services/awslambda/lambda_api.py", line 602, in run_lambda
localstack_serverless1 | result = LAMBDA_EXECUTOR.execute(func_arn, func_details, event, context=context,
localstack_serverless1 | File "/opt/code/localstack/localstack/services/awslambda/lambda_executors.py", line 176, in execute
localstack_serverless1 | return do_execute()
localstack_serverless1 | File "/opt/code/localstack/localstack/services/awslambda/lambda_executors.py", line 168, in do_execute
localstack_serverless1 | return _run(func_arn=func_arn)
localstack_serverless1 | File "/opt/code/localstack/localstack/utils/cloudwatch/cloudwatch_util.py", line 149, in wrapped
localstack_serverless1 | raise e
localstack_serverless1 | File "/opt/code/localstack/localstack/utils/cloudwatch/cloudwatch_util.py", line 145, in wrapped
localstack_serverless1 | result = func(*args, **kwargs)
localstack_serverless1 | File "/opt/code/localstack/localstack/services/awslambda/lambda_executors.py", line 159, in _run
localstack_serverless1 | raise e
localstack_serverless1 | File "/opt/code/localstack/localstack/services/awslambda/lambda_executors.py", line 147, in _run
localstack_serverless1 | result = self._execute(func_arn, func_details, event, context, version)
localstack_serverless1 | File "/opt/code/localstack/localstack/services/awslambda/lambda_executors.py", line 325, in _execute
localstack_serverless1 | result = self.run_lambda_executor(cmd, stdin, env_vars=environment, func_details=func_details)
localstack_serverless1 | File "/opt/code/localstack/localstack/services/awslambda/lambda_executors.py", line 231, in run_lambda_executor
localstack_serverless1 | raise InvocationException('Lambda process returned error status code: %s. Result: %s. Output:\n%s' %
localstack_serverless1 | localstack.services.awslambda.lambda_executors.InvocationException: Lambda process returned error status code: 1. Result: . Output:
localstack_serverless1 | Unable to find image 'lambci/lambda:nodejs10.x' locally
localstack_serverless1 | Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
localstack_serverless1 | must specify at least one container source
localstack_serverless1 | json: cannot unmarshal array into Go value of type types.ContainerJSON
localstack_serverless1 |
I got this working by changing docker-compose.yml to the following:
version: '3.2'
services:
localstack:
image: localstack/localstack-full:latest
container_name: localstack_serverless1
ports:
- '4566:4566'
- '4571:4571'
- '8055:8080'
environment:
# - HOSTNAME_EXTERNAL=localstack
- COMPOSE_CONVERT_WINDOWS_PATHS=1
- DEBUG=1
- DATA_DIR=/tmp/localstack/data
- LAMBDA_EXECUTOR=docker
- START_WEB=1
- DOCKER_HOST=unix:///var/run/docker.sock
- HOST_TMP_FOLDER=./.localstack
volumes:
- './.localstack:/tmp/localstack'
- '/var/run/docker.sock:/var/run/docker.sock' # I don't understand what this corresponds to on my PC? But it is the only option I can get to work!
The last line is very curious, as I don't understand what that maps to on my windows PC?

Access files in Swift Package [duplicate]

I'm trying to use a resource file in unit tests and access it with Bundle.path, but it returns nil.
This call in MyProjectTests.swift returns nil:
Bundle(for: type(of: self)).path(forResource: "TestAudio", ofType: "m4a")
Here is my project hierarchy. I also tried moving TestAudio.m4a to a Resources folder:
├── Package.swift
├── Sources
│   └── MyProject
│   ├── ...
└── Tests
└── MyProjectTests
├── MyProjectTests.swift
└── TestAudio.m4a
Here is my package description:
// swift-tools-version:4.0
import PackageDescription
let package = Package(
name: "MyProject",
products: [
.library(
name: "MyProject",
targets: ["MyProject"])
],
targets: [
.target(
name: "MyProject",
dependencies: []
),
.testTarget(
name: "MyProjectTests",
dependencies: ["MyProject"]
),
]
)
I am using Swift 4 and the Swift Package Manager Description API version 4.
Swift 5.3
See Apple Documentation: "Bundling Resources with a Swift Package"
Swift 5.3 includes Package Manager Resources SE-0271 evolution proposal with "Status: Implemented (Swift 5.3)".
Resources aren't always intended for use by clients of the package; one use of resources might include test fixtures that are only needed by unit tests. Such resources would not be incorporated into clients of the package along with the library code, but would only be used while running the package's tests.
Add a new resources parameter in target and testTarget APIs to allow declaring resource files explicitly.
SwiftPM uses file system conventions for determining the set of source files that belongs to each target in a package: specifically, a target's source files are those that are located underneath the designated "target directory" for the target. By default this is a directory that has the same name as the target and is located in "Sources" (for a regular target) or "Tests" (for a test target), but this location can be customized in the package manifest.
// Get path to DefaultSettings.plist file.
let path = Bundle.module.path(forResource: "DefaultSettings", ofType: "plist")
// Load an image that can be in an asset archive in a bundle.
let image = UIImage(named: "MyIcon", in: Bundle.module, compatibleWith: UITraitCollection(userInterfaceStyle: .dark))
// Find a vertex function in a compiled Metal shader library.
let shader = try mtlDevice.makeDefaultLibrary(bundle: Bundle.module).makeFunction(name: "vertexShader")
// Load a texture.
let texture = MTKTextureLoader(device: mtlDevice).newTexture(name: "Grass", scaleFactor: 1.0, bundle: Bundle.module, options: options)
Example
// swift-tools-version:5.3
import PackageDescription
targets: [
.target(
name: "Example",
dependencies: [],
resources: [
// Apply platform-specific rules.
// For example, images might be optimized per specific platform rule.
// If path is a directory, the rule is applied recursively.
// By default, a file will be copied if no rule applies.
// Process file in Sources/Example/Resources/*
.process("Resources"),
]),
.testTarget(
name: "ExampleTests",
dependencies: [Example],
resources: [
// Copy Tests/ExampleTests/Resources directories as-is.
// Use to retain directory structure.
// Will be at top level in bundle.
.copy("Resources"),
]),
Reported Issues & Possible Workarounds
Swift 5.3 SPM Resources in tests uses wrong bundle path?
Swift Package Manager - Resources in test targets
Xcode
Bundle.module is generated by SwiftPM (see Build/BuildPlan.swift SwiftTargetBuildDescription generateResourceAccessor()) and thus not present in Foundation.Bundle when built by Xcode.
A comparable approach in Xcode would be to:
manually add a Resources reference folder to the Xcode project,
add an Xcode build phase copy to put the Resource into some *.bundle directory,
add a some custom #ifdef XCODE_BUILD compiler directive for the Xcode build to work with the resources.
#if XCODE_BUILD
extension Foundation.Bundle {
/// Returns resource bundle as a `Bundle`.
/// Requires Xcode copy phase to locate files into `ExecutableName.bundle`;
/// or `ExecutableNameTests.bundle` for test resources
static var module: Bundle = {
var thisModuleName = "CLIQuickstartLib"
var url = Bundle.main.bundleURL
for bundle in Bundle.allBundles where bundle.bundlePath.hasSuffix(".xctest") {
url = bundle.bundleURL.deletingLastPathComponent()
thisModuleName = thisModuleName.appending("Tests")
}
url = url.appendingPathComponent("\(thisModuleName).bundle")
guard let bundle = Bundle(url: url) else {
fatalError("Foundation.Bundle.module could not load resource bundle: \(url.path)")
}
return bundle
}()
/// Directory containing resource bundle
static var moduleDir: URL = {
var url = Bundle.main.bundleURL
for bundle in Bundle.allBundles where bundle.bundlePath.hasSuffix(".xctest") {
// remove 'ExecutableNameTests.xctest' path component
url = bundle.bundleURL.deletingLastPathComponent()
}
return url
}()
}
#endif
SwiftPM (5.1) does not support resources natively yet, however...
When unit tests are running, the repository can be expected to be available, so simply load the resource with something derived from #file. This works with all extant versions of SwiftPM.
let thisSourceFile = URL(fileURLWithPath: #file)
let thisDirectory = thisSourceFile.deletingLastPathComponent()
let resourceURL = thisDirectory.appendingPathComponent("TestAudio.m4a")
In cases other than tests, where the repository will not be around at runtime, resources can still be included, albeit at the expense of the binary size. Any arbitrary file can be embedded into Swift source by expressing it as base 64 data in a string literal. Workspace is an open‐source tool that can automate that process: $ workspace refresh resources. (Disclaimer: I am its author.)
Bundle.module started to work for me after right file structure and dependencies setup.
File structure for test target:
Dependencies setup in Package.swift:
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: "Parser",
dependencies: []),
.testTarget(
name: "ParserTests",
dependencies: ["Parser"],
resources: [
.copy("Resources/test.txt")
]
),
]
Usage in the project:
private var testData: Data {
let url = Bundle.module.url(forResource: "test", withExtension: "txt")!
let data = try! Data(contentsOf: url)
return data
}
A Swift script approach for Swift 5.2 and earlier...
Swift Package Manager (SwiftPM)
It is possible to use resources in unit tests with SwiftPM for both macOS and Linux with some additional setup and custom scripts. Here is a description of one possible approach:
The SwiftPM does not yet provide a mechanism for handling resources. The following is a workable approach for using test resources TestResources/ within a package; and, also provides for a consistent TestScratch/ directory for creating test files if needed.
Setup:
Add test resources directory TestResources/ in the PackageName/ directory.
For Xcode use, add test resources to project "Build Phases" for the test bundle target.
Project Editor > TARGETS > CxSQLiteFrameworkTests > Build Phases > Copy Files: Destination Resources, + add files
For command line use, set up Bash aliases which include swift-copy-testresources.swift
Place an executable version of swift-copy-testresources.swift on an appropriate path which is included $PATH.
Ubuntu: nano ~/bin/ swift-copy-testresources.swift
Bash Aliases
macOS: nano .bash_profile
alias swiftbuild='swift-copy-testresources.swift $PWD; swift build -Xswiftc "-target" -Xswiftc "x86_64-apple-macosx10.13";'
alias swifttest='swift-copy-testresources.swift $PWD; swift test -Xswiftc "-target" -Xswiftc "x86_64-apple-macosx10.13";'
alias swiftxcode='swift package generate-xcodeproj --xcconfig-overrides Package.xcconfig; echo "REMINDER: set Xcode build system."'
Ubuntu: nano ~/.profile. Apppend to end. Change /opt/swift/current to where Swift is installed for a given system.
#############
### SWIFT ###
#############
if [ -d "/opt/swift/current/usr/bin" ] ; then
PATH="/opt/swift/current/usr/bin:$PATH"
fi
alias swiftbuild='swift-copy-testresources.swift $PWD; swift build;'
alias swifttest='swift-copy-testresources.swift $PWD; swift test;'
Script: swift-copy-testresources.sh chmod +x
#!/usr/bin/swift
// FILE: swift-copy-testresources.sh
// verify swift path with "which -a swift"
// macOS: /usr/bin/swift
// Ubuntu: /opt/swift/current/usr/bin/swift
import Foundation
func copyTestResources() {
let argv = ProcessInfo.processInfo.arguments
// for i in 0..<argv.count {
// print("argv[\(i)] = \(argv[i])")
// }
let pwd = argv[argv.count-1]
print("Executing swift-copy-testresources")
print(" PWD=\(pwd)")
let fm = FileManager.default
let pwdUrl = URL(fileURLWithPath: pwd, isDirectory: true)
let srcUrl = pwdUrl
.appendingPathComponent("TestResources", isDirectory: true)
let buildUrl = pwdUrl
.appendingPathComponent(".build", isDirectory: true)
let dstUrl = buildUrl
.appendingPathComponent("Contents", isDirectory: true)
.appendingPathComponent("Resources", isDirectory: true)
do {
let contents = try fm.contentsOfDirectory(at: srcUrl, includingPropertiesForKeys: [])
do { try fm.removeItem(at: dstUrl) } catch { }
try fm.createDirectory(at: dstUrl, withIntermediateDirectories: true)
for fromUrl in contents {
try fm.copyItem(
at: fromUrl,
to: dstUrl.appendingPathComponent(fromUrl.lastPathComponent)
)
}
} catch {
print(" SKIP TestResources not copied. ")
return
}
print(" SUCCESS TestResources copy completed.\n FROM \(srcUrl)\n TO \(dstUrl)")
}
copyTestResources()
Test Utility Code
////////////////
// MARK: - Linux
////////////////
#if os(Linux)
// /PATH_TO_PACKAGE/PackageName/.build/TestResources
func getTestResourcesUrl() -> URL? {
guard let packagePath = ProcessInfo.processInfo.environment["PWD"]
else { return nil }
let packageUrl = URL(fileURLWithPath: packagePath)
let testResourcesUrl = packageUrl
.appendingPathComponent(".build", isDirectory: true)
.appendingPathComponent("TestResources", isDirectory: true)
return testResourcesUrl
}
// /PATH_TO_PACKAGE/PackageName/.build/TestScratch
func getTestScratchUrl() -> URL? {
guard let packagePath = ProcessInfo.processInfo.environment["PWD"]
else { return nil }
let packageUrl = URL(fileURLWithPath: packagePath)
let testScratchUrl = packageUrl
.appendingPathComponent(".build")
.appendingPathComponent("TestScratch")
return testScratchUrl
}
// /PATH_TO_PACKAGE/PackageName/.build/TestScratch
func resetTestScratch() throws {
if let testScratchUrl = getTestScratchUrl() {
let fm = FileManager.default
do {_ = try fm.removeItem(at: testScratchUrl)} catch {}
_ = try fm.createDirectory(at: testScratchUrl, withIntermediateDirectories: true)
}
}
///////////////////
// MARK: - macOS
///////////////////
#elseif os(macOS)
func isXcodeTestEnvironment() -> Bool {
let arg0 = ProcessInfo.processInfo.arguments[0]
// Use arg0.hasSuffix("/usr/bin/xctest") for command line environment
return arg0.hasSuffix("/Xcode/Agents/xctest")
}
// /PATH_TO/PackageName/TestResources
func getTestResourcesUrl() -> URL? {
let testBundle = Bundle(for: CxSQLiteFrameworkTests.self)
let testBundleUrl = testBundle.bundleURL
if isXcodeTestEnvironment() { // test via Xcode
let testResourcesUrl = testBundleUrl
.appendingPathComponent("Contents", isDirectory: true)
.appendingPathComponent("Resources", isDirectory: true)
return testResourcesUrl
}
else { // test via command line
guard let packagePath = ProcessInfo.processInfo.environment["PWD"]
else { return nil }
let packageUrl = URL(fileURLWithPath: packagePath)
let testResourcesUrl = packageUrl
.appendingPathComponent(".build", isDirectory: true)
.appendingPathComponent("TestResources", isDirectory: true)
return testResourcesUrl
}
}
func getTestScratchUrl() -> URL? {
let testBundle = Bundle(for: CxSQLiteFrameworkTests.self)
let testBundleUrl = testBundle.bundleURL
if isXcodeTestEnvironment() {
return testBundleUrl
.deletingLastPathComponent()
.appendingPathComponent("TestScratch")
}
else {
return testBundleUrl
.deletingLastPathComponent()
.deletingLastPathComponent()
.deletingLastPathComponent()
.appendingPathComponent("TestScratch")
}
}
func resetTestScratch() throws {
if let testScratchUrl = getTestScratchUrl() {
let fm = FileManager.default
do {_ = try fm.removeItem(at: testScratchUrl)} catch {}
_ = try fm.createDirectory(at: testScratchUrl, withIntermediateDirectories: true)
}
}
#endif
File Locations:
Linux
During the swift build and swift test the process environment variable PWD provides a path the package root …/PackageName. The PackageName/TestResources/ files are copied to $PWD/.buid/TestResources. The TestScratch/ directory, if used during test runtime, is created in $PWD/.buid/TestScratch.
.build/
├── debug -> x86_64-unknown-linux/debug
...
├── TestResources
│ └── SomeTestResource.sql <-- (copied from TestResources/)
├── TestScratch
│ └── SomeTestProduct.sqlitedb <-- (created by running tests)
└── x86_64-unknown-linux
└── debug
├── PackageName.build/
│ └── ...
├── PackageNamePackageTests.build
│ └── ...
├── PackageNamePackageTests.swiftdoc
├── PackageNamePackageTests.swiftmodule
├── PackageNamePackageTests.xctest <-- executable, not Bundle
├── PackageName.swiftdoc
├── PackageName.swiftmodule
├── PackageNameTests.build
│ └── ...
├── PackageNameTests.swiftdoc
├── PackageNameTests.swiftmodule
└── ModuleCache ...
macOS CLI
.build/
|-- TestResources/
| `-- SomeTestResource.sql <-- (copied from TestResources/)
|-- TestScratch/
| `-- SomeTestProduct.sqlitedb <-- (created by running tests)
...
|-- debug -> x86_64-apple-macosx10.10/debug
`-- x86_64-apple-macosx10.10
`-- debug
|-- PackageName.build/
|-- PackageName.swiftdoc
|-- PackageName.swiftmodule
|-- PackageNamePackageTests.xctest
| `-- Contents
| `-- MacOS
| |-- PackageNamePackageTests
| `-- PackageNamePackageTests.dSYM
...
`-- libPackageName.a
macOS Xcode
PackageName/TestResources/ files are copied into the test bundle Contents/Resources folder as part of the Build Phases. If used during tests, TestScratch/ is placed alongside the *xctest bundle.
Build/Products/Debug/
|-- PackageNameTests.xctest/
| `-- Contents/
| |-- Frameworks/
| | |-- ...
| | `-- libswift*.dylib
| |-- Info.plist
| |-- MacOS/
| | `-- PackageNameTests
| `-- Resources/ <-- (aka TestResources/)
| |-- SomeTestResource.sql <-- (copied from TestResources/)
| `-- libswiftRemoteMirror.dylib
`-- TestScratch/
`-- SomeTestProduct.sqlitedb <-- (created by running tests)
I also posted a GitHubGist of this same approach at 004.4'2 SW Dev Swift Package Manager (SPM) With Resources Qref
I found another solution looking at this file.
It's possible to create a bundle with a path, for example:
let currentBundle = Bundle.allBundles.filter() { $0.bundlePath.hasSuffix(".xctest") }.first!
let realBundle = Bundle(path: "\(currentBundle.bundlePath)/../../../../Tests/MyProjectTests/Resources")
It's a bit ugly, but if you want to avoid a Makefile, it works.
starting on Swift 5.3, thanks to SE-0271, you can add bundle resources on swift package manager by adding resources on your .target declaration.
example:
.target(
name: "HelloWorldProgram",
dependencies: [],
resources: [.process(Images), .process("README.md")]
)
if you want to learn more, I have written an article on medium, discussing this topic. I don't specifically discuss .testTarget, but looking on the swift proposal, it looks alike.
I'm using:
extension Bundle {
func locateFirst(forResource: String, withExtension: String) -> URL? {
for b in Bundle.allBundles {
if let u = b.url(forResource: forResource, withExtension: withExtension) {
return u
}
}
return nil
}
}
'''
And then just call locateFirst, which gives the first item.
like:
'''
let p12 = Bundle().locateFirst(forResource: "Certificates", withExtension: "p12")!
'''
A made a simple solution that works for legacy swift and future swift:
Add your assets in the root of your project
In your swift code: ResourceHelper.projectRootURL(projectRef: #file, fileName: "temp.bundle/payload.json").path
Works in Xcode and swift build in terminal or github actions 🎉
https://eon.codes/blog/2020/01/04/How-to-include-assets-with-swift-package-manager/ and https://github.com/eonist/ResourceHelper/

How to copy a file from local machine to a storage account using Terraform

I have created a storage account and created a file share in it too using Terraform. I want to copy some files from my local machine to that storage account using Terraform. Is that possible? If yes, then how?
Here is my code-
provider "azurerm" {
# whilst the `version` attribute is optional, we recommend pinning to a given version of the Provider
version = "=2.0.0"
subscription_id = "xxx-xxxx-xxxx-xxxx"
tenant_id = "xxxxx-xxxxx-xxxx-xxxx"
features {}
}
resource "azurerm_resource_group" "example" {
name = "azuretest"
location = "West Europe"
}
resource "azurerm_storage_account" "example" {
name = "asdfghjklteststorage"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
account_tier = "Standard"
account_replication_type = "LRS"
}
resource "azurerm_storage_share" "example" {
name = "sharename"
storage_account_name = azurerm_storage_account.example.name
quota = 50
acl {
id = "xxx-xxx-xxx-xxx"
access_policy {
permissions = "rwdl"
start = "2020-05-10T09:38:21.0000000Z"
expiry = "2020-07-02T10:38:21.0000000Z"
}
}
}
resource "null_resource" "uploadfile" {
provisioner "local-exec" {
command = <<-EOT
$storageAcct = Get-AzStorageAccount -ResourceGroupName "${azurerm_resource_group.example.name}" -Name "${azurerm_storage_account.example.name}"
Set-AzStorageFileContent `
-Context $storageAcct.Context `
-ShareName "${azurerm_storage_share.example.name}" `
-Source "C:\Users\xxx\xxx\xxx\Untitled.png" `
-Path "Untitled.png"
EOT
interpreter = ["PowerShell", "-Command"]
}
}
You could use local-exec provisioner invokes a local executable after a resource is created. See upload a file to Azure file share with PowerShell.
For example,
resource "azurerm_storage_share" "example" {
name = "sharename"
storage_account_name = azurerm_storage_account.example.name
quota = 50
acl {
id = "xxxxxxxxxxxxxxx"
access_policy {
permissions = "rwdl"
start = "2020-05-10T09:38:21.0000000Z"
expiry = "2020-07-02T10:38:21.0000000Z"
}
}
}
resource "null_resource" "uploadfile" {
provisioner "local-exec" {
command = <<-EOT
$storageAcct = Get-AzStorageAccount -ResourceGroupName "${azurerm_resource_group.example.name}" -Name "${azurerm_storage_account.example.name}"
Set-AzStorageFileContent `
-Context $storageAcct.Context `
-ShareName "${azurerm_storage_share.example.name}" `
-Source "C:\Users\xxx\terraform\test.txt" `
-Path "test.txt"
EOT
interpreter = ["PowerShell", "-Command"]
}
}
Result
For more information, you could read this blog.
For anyone coming from Google, it's worth pointing out you that in early 2022 should now be able to use azurerm_storage_share_file. This worked great for me to upload a single file. To upload multiple files it looks like you will require multiple resources
https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_share_file
resource "azurerm_storage_share_file" "example" {
name = "test.txt"
storage_share_id = azurerm_storage_share.example.id
source = "${path.root}/TestFiles/test.txt"
}

LoadFileUrl and LoadHtmlString not loading local document resources

Basically using HybridWebView which uses WKWebview I'm loading a downloading an html file with a bunch of css files that are stored in the app documents directory.
Example
var/mobile/Containers/Data/Application/C9D9BB56-79B6-4990-A599-18C6AD928A22/Documents
I can load the html just fine using LoadFileUrl or LoadHTMLString, the issue is that the referenced css and js does not load into the webview
This is my file url
file:///var/mobile/Containers/Data/Application/C9D9BB56-79B6-4990-A599-18C6AD928A22/Documents/Courses/2d7d0a7d-145a-41d0-9abf-685a2b5dfc3c/Online_Placement_Test_no_timer_pack/YKZOP4NACH3EPJNTG6M4T2BQDI/Unit_4_5/995/Unit.html
Base Url
file:///var/mobile/Containers/Data/Application/C9D9BB56-79B6-4990-A599-18C6AD928A22/Documents/Courses/2d7d0a7d-145a-41d0-9abf-685a2b5dfc3c/Online_Placement_Test_no_timer_pack/YKZOP4NACH3EPJNTG6M4T2BQDI/Unit_4_5/995/
And this is an example of a path to a resource that doesn't load grabbed from the network inspector in Safari.
file:///var/mobile/Containers/Data/Application/C9D9BB56-79B6-4990-A599-18C6AD928A22/Documents/Courses/2d7d0a7d-145a-41d0-9abf-685a2b5dfc3c/Online_Placement_Test_no_timer_pack/YKZOP4NACH3EPJNTG6M4T2BQDI/Unit_4_5/995/js/bootstrap.min.js
Not sure what I'm doing wrong here. I've even set
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsLocalNetworking</key>
<true/>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
in info.plist
You can obtain the doc dir via NSFileManager.DefaultManager.GetUrl.
Example loading "WebSite" from App's document directory
var docsDir = NSFileManager.DefaultManager.GetUrl(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomain.User, null, true, out var error);
var data = NSUrl.FromFilename(Path.Combine(docsDir.Path, "WebSite", "index.html"));
var content = NSUrl.FromFilename(Path.Combine(docsDir.Path, "WebSite"));
webView.LoadFileUrl(data, content);
Example loading "WebSite" from bundled resources:
var bundlePath = NSBundle.MainBundle.BundlePath;
var data = NSUrl.FromFilename(Path.Combine(bundlePath, "WebSite", "index.html"));
var content = NSUrl.FromFilename(Path.Combine(bundlePath, "WebSite"));
webView.LoadFileUrl(data, content);
Using an downloaded Azure sample website
Note: Downloaded to a WebSite subdir within NSSearchPathDirectory.DocumentDirectory
├── css
│   └── site.css
├── fonts
│   └── segoeuil.ttf
├── img
│   ├── cloneWhite.svg
│   ├── deployWhite.svg
│   ├── lightbulbWhite.svg
│   ├── stackWhite.svg
│   ├── successCloudNew.svg
│   └── tweetThis.svg
└── index.html
Local Output:
Loading a locally stored website or html-File from the filesystem's App's caches directory using WebKit WKWebView in Objective-C in iOS13
Note the very important webView.configuration.preferences setting allowFileAccessFromFileURLs!!
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *docsDir = [paths objectAtIndex:0];
NSString *downloadDir = [[NSString alloc] initWithFormat:#"%#/%#", docsDir, #"www"];
NSURL* downloadDirUrl = [[NSURL alloc] initFileURLWithPath:downloadDir];
NSLog(#"DIR '%#'", downloadDirUrl);
NSURL* indexHtmlUrl = [[NSURL alloc] initWithString:[[NSString alloc] initWithFormat:#"%#/%#", downloadDir, #"/index.html?param=val"]];
NSLog(#"HTML '%#'", indexHtmlUrl);
WKWebView* webView = ...;
[webView.configuration.preferences setValue:#YES forKey:#"allowFileAccessFromFileURLs"];
[webView loadFileURL:indexHtmlUrl allowingReadAccessToURL:downloadDirUrl];

Using Socket IO with Express JS

(Not familiar with node.)
I generated my express js app using the express-generator
so the file structure looks like this
├── app.js
├── bin
│ └── www
├── package.json
├── public
│ ├── images
│ ├── javascripts
│ └── stylesheets
│ └── style.css
├── routes
│ ├── index.js
│ └── users.js
└── views
├── error.jade
├── index.jade
└── layout.jade
I wanted to implement socket io. so on file bin/www
I added this code below server.listen(port);
server.listen(port);
/**
* Socket IO
*/
var io = require('socket.io')(server);
io.on('connection', function(socket){
console.log('a user connected');
console.log(socket.id);
socket.on('disconnect', function(){
console.log('user disconnected');
console.log(socket.id);
});
});
every time a client connect, it logs
a user connected
now I want to post an update to a specific user using their socket.id
on routes/index.js
var express = require('express');
var router = express.Router();
var io = require('socket.io');
/* GET home page. */
router.route('/')
.get(function(req, res, next)
{
res.send('Nothing to do here');
})
.post(function(req, res, next)
{
var socketid = req.param('socketid');
io.broadcast.to(id).emit('message', "Hello World");
}
);
module.exports = router;
Now Every time I post. I get an error
Cannot read property 'to' of undefined
it seems that I got a wrong io.
should I require also the server inside my index.js?
or how can I use the one io var declared in www? is this possible? just use the existing objects already
You are getting Cannot read property 'to' of undefined, because you have not defined io in routes\index.js file and you don't have reference to io in bin/www.
You can resolve the issue by passing the newly io object to the routes file.
e.g.
bin/www
server.listen(port);
/**
* Socket IO
*/
var io = require('socket.io')(server);
//remove same lines from app.js
var routes = require('./router/index.js')(io);
app.use('/', routes)
io.on('connection', function(socket){
console.log('a user connected');
console.log(socket.id);
socket.on('disconnect', function(){
console.log('user disconnected');
console.log(socket.id);
});
});
router/index.js
module.exports = function(io) {
var express = require('express');
var router = express.Router();
/* GET home page. */
router.route('/').get(function(req, res, next){
res.send('Nothing to do here');
}).post(function(req, res, next){
var socketid = req.param('socketid');
io.broadcast.to(id).emit('message', "Hello World");
});
return router;
}
Let me know, if it doesn't work.

Resources