Skip to content

Commit

Permalink
Merge branch 'main' into multiple-yaml-documents
Browse files Browse the repository at this point in the history
  • Loading branch information
devtribe authored Dec 27, 2024
2 parents dc75951 + 4702dda commit d8b3b4f
Show file tree
Hide file tree
Showing 46 changed files with 296 additions and 89 deletions.
9 changes: 9 additions & 0 deletions packages/backend/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# backend

## 2.3.2

### Patch Changes

- Updated dependencies [30883b0]
- Updated dependencies [2bf0fa2]
- @roadiehq/catalog-backend-module-aws@5.4.1
- @roadiehq/backstage-plugin-argo-cd-backend@3.3.1

## 2.3.1

### Patch Changes
Expand Down
6 changes: 3 additions & 3 deletions packages/backend/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "backend",
"version": "2.3.1",
"version": "2.3.2",
"main": "dist/index.cjs.js",
"types": "src/index.ts",
"private": true,
Expand Down Expand Up @@ -41,11 +41,11 @@
"@langchain/core": "^0.2.27",
"@langchain/openai": "^0.2.7",
"@octokit/rest": "^19.0.3",
"@roadiehq/backstage-plugin-argo-cd-backend": "3.3.0",
"@roadiehq/backstage-plugin-argo-cd-backend": "3.3.1",
"@roadiehq/plugin-wiz-backend": "^1.0.7",
"@roadiehq/backstage-plugin-aws-auth": "^0.5.0",
"@roadiehq/backstage-plugin-aws-backend": "^1.3.0",
"@roadiehq/catalog-backend-module-aws": "^5.3.0",
"@roadiehq/catalog-backend-module-aws": "^5.4.1",
"@roadiehq/catalog-backend-module-okta": "^1.0.3",
"@roadiehq/rag-ai-backend": "^1.3.0",
"@roadiehq/rag-ai-backend-embeddings-aws": "^1.0.0",
Expand Down
6 changes: 6 additions & 0 deletions plugins/backend/backstage-plugin-argo-cd-backend/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# @roadiehq/backstage-plugin-argo-cd-backend

## 3.3.1

### Patch Changes

- 2bf0fa2: Adding the `resources-finalizer.argocd.argoproj.io` finalizer when creating a project. This allows the ability to delete the project first without getting stuck when deleting the application afterwards. This fix will allow the application to delete and not get stuck deleting.

## 3.3.0

### Minor Changes
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@roadiehq/backstage-plugin-argo-cd-backend",
"version": "3.3.0",
"version": "3.3.1",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ export class ArgoService implements ArgoServiceApi {
metadata: {
name: projectName,
resourceVersion,
finalizers: ['resources-finalizer.argocd.argoproj.io'],
},
spec: {
destinations: [
Expand Down Expand Up @@ -350,6 +351,7 @@ export class ArgoService implements ArgoServiceApi {
},
body: JSON.stringify(data),
};

const resp = await fetch(`${baseUrl}/api/v1/projects`, options);
const responseData = await resp.json();
if (resp.status === 403) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,39 @@ describe('ArgoCD service', () => {
},
});
});

it('creates project with resources-finalizer.argocd.argoproj.io finalizer', async () => {
fetchMock.mockResponseOnce(
JSON.stringify({
argocdCreateProjectResp,
}),
);
const service = new ArgoService(
'testusername',
'testpassword',
getConfig({
token: 'token',
}),
loggerMock,
);

await service.createArgoProject({
baseUrl: 'baseUrl',
argoToken: 'token',
projectName: 'projectName',
namespace: 'namespace',
sourceRepo: 'sourceRepo',
});

expect(fetchMock).toHaveBeenCalledWith(
expect.any(String),
expect.objectContaining({
body: expect.stringContaining(
'{"metadata":{"name":"projectName","finalizers":["resources-finalizer.argocd.argoproj.io"]}',
),
}),
);
});
});

describe('createArgoApplication', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ export type Metadata = {
deletionTimestamp?: string;
deletionGracePeriodSeconds?: number;
resourceVersion?: string;
finalizers?: string[];
};

export type ResourceItem = {
Expand Down
30 changes: 30 additions & 0 deletions plugins/backend/catalog-backend-module-aws/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,35 @@
# @backstage/plugin-catalog-backend-module-aws

## 5.5.0

### Minor Changes

- 1a18001: Add tag mapping for SNS Resource Provider

## 5.4.4

### Patch Changes

- e91c9e4: Add test, debug logging and RDS support for ownerTag mapping

## 5.4.3

### Patch Changes

- 8fdf8c1: Use region from config in dynamo table provider

## 5.4.2

### Patch Changes

- 7a10368: Add more providers to allow custom label mapping

## 5.4.1

### Patch Changes

- 30883b0: Allow custom label mapping for new AWS providers

## 5.4.0

### Minor Changes
Expand Down
2 changes: 1 addition & 1 deletion plugins/backend/catalog-backend-module-aws/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@roadiehq/catalog-backend-module-aws",
"description": "A set of Backstage catalog providers for AWS",
"version": "5.4.0",
"version": "5.5.0",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,12 @@ export class AWSDynamoDbTableProvider extends AWSEntityProvider {
}

private async getDdb(dynamicAccountConfig?: DynamicAccountConfig) {
const { region } = this.getParsedConfig(dynamicAccountConfig);
const credentials = this.useTemporaryCredentials
? this.getCredentials(dynamicAccountConfig)
: await this.getCredentialsProvider();
return this.useTemporaryCredentials
? new DynamoDB({ credentials })
? new DynamoDB({ credentials, region })
: new DynamoDB(credentials);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ import * as winston from 'winston';
import { LoggerService } from '@backstage/backend-plugin-api';
import { Config } from '@backstage/config';
import { AWSEntityProvider } from './AWSEntityProvider';
import { ownerFromTags, relationshipsFromTags } from '../utils/tags';
import {
LabelValueMapper,
ownerFromTags,
relationshipsFromTags,
} from '../utils/tags';
import { CatalogApi } from '@backstage/catalog-client';
import { AccountConfig, DynamicAccountConfig } from '../types';
import { duration } from '../utils/timer';
Expand All @@ -39,6 +43,7 @@ export class AWSElastiCacheEntityProvider extends AWSEntityProvider {
providerId?: string;
ownerTag?: string;
useTemporaryCredentials?: boolean;
labelValueMapper?: LabelValueMapper;
},
) {
const accountId = config.getString('accountId');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@
* limitations under the License.
*/

import { Lambda, ListFunctionsCommand } from '@aws-sdk/client-lambda';
import {
Lambda,
ListFunctionsCommand,
ListTagsCommand,
} from '@aws-sdk/client-lambda';
import { STS, GetCallerIdentityCommand } from '@aws-sdk/client-sts';

import { mockClient } from 'aws-sdk-client-mock';
Expand All @@ -31,6 +35,7 @@ const logger = createLogger({
});

describe('AWSLambdaFunctionProvider', () => {
const ownerTag = 'Owner-test';
const config = new ConfigReader({
accountId: '123456789012',
roleName: 'arn:aws:iam::123456789012:role/role1',
Expand Down Expand Up @@ -64,6 +69,7 @@ describe('AWSLambdaFunctionProvider', () => {
});

describe('where there are is a function', () => {
const owner = 'engineering';
beforeEach(() => {
lambda.on(ListFunctionsCommand).resolves({
Functions: [
Expand All @@ -86,6 +92,12 @@ describe('AWSLambdaFunctionProvider', () => {
},
],
});
lambda.on(ListTagsCommand).resolves({
Tags: {
[ownerTag]: owner,
owner: 'wrong',
},
});
});

it('creates aws functions', async () => {
Expand Down Expand Up @@ -130,6 +142,32 @@ describe('AWSLambdaFunctionProvider', () => {
});
});

it('maps owner from custom tag mapping', async () => {
const entityProviderConnection: EntityProviderConnection = {
applyMutation: jest.fn(),
refresh: jest.fn(),
};
const provider = AWSLambdaFunctionProvider.fromConfig(config, {
logger,
ownerTag,
});
provider.connect(entityProviderConnection);
await provider.run();
expect(entityProviderConnection.applyMutation).toHaveBeenCalledWith({
type: 'full',
entities: [
expect.objectContaining({
entity: expect.objectContaining({
kind: 'Resource',
spec: expect.objectContaining({
owner: owner,
}),
}),
}),
],
});
});

it('is able to use dynamic config', async () => {
const entityProviderConnection: EntityProviderConnection = {
applyMutation: jest.fn(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,14 @@ export class AWSLambdaFunctionProvider extends AWSEntityProvider {
if (lambdaFunction.Role) {
annotations[ANNOTATION_AWS_IAM_ROLE_ARN] = lambdaFunction.Role;
}
const owner = ownerFromTags(tags, this.getOwnerTag(), groups);
const relationships = relationshipsFromTags(tags);
this.logger.debug(
`Setting Lambda owner from tags as ${owner} and relationships of ${JSON.stringify(
relationships,
)}`,
);

lambdaComponents.push({
kind: 'Resource',
apiVersion: 'backstage.io/v1beta1',
Expand All @@ -144,8 +152,8 @@ export class AWSLambdaFunctionProvider extends AWSEntityProvider {
labels: this.labelsFromTags(tags),
},
spec: {
owner: ownerFromTags(tags, this.getOwnerTag(), groups),
...relationshipsFromTags(tags),
owner: owner,
...relationships,
type: 'lambda-function',
},
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ import * as winston from 'winston';
import { LoggerService } from '@backstage/backend-plugin-api';
import { Config } from '@backstage/config';
import { AWSEntityProvider } from './AWSEntityProvider';
import { ownerFromTags, relationshipsFromTags } from '../utils/tags';
import {
LabelValueMapper,
ownerFromTags,
relationshipsFromTags,
} from '../utils/tags';
import { CatalogApi } from '@backstage/catalog-client';
import { AccountConfig, DynamicAccountConfig } from '../types';
import { duration } from '../utils/timer';
Expand All @@ -40,6 +44,7 @@ export class AWSOpenSearchEntityProvider extends AWSEntityProvider {
providerId?: string;
ownerTag?: string;
useTemporaryCredentials?: boolean;
labelValueMapper?: LabelValueMapper;
},
) {
const accountId = config.getString('accountId');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export class AWSRDSProvider extends AWSEntityProvider {
providerId?: string;
useTemporaryCredentials?: boolean;
labelValueMapper?: LabelValueMapper;
ownerTag?: string;
},
) {
const accountId = config.getString('accountId');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@
* limitations under the License.
*/

import { SNS, ListTopicsCommand, Topic } from '@aws-sdk/client-sns';
import {
SNS,
ListTopicsCommand,
Topic,
ListTagsForResourceCommand,
} from '@aws-sdk/client-sns';
import { STS, GetCallerIdentityCommand } from '@aws-sdk/client-sts';

import { mockClient } from 'aws-sdk-client-mock';
Expand Down Expand Up @@ -47,6 +52,9 @@ describe('AWSSNSTopicProvider', () => {
sns.on(ListTopicsCommand).resolves({
Topics: [],
});
sns.on(ListTagsForResourceCommand).resolves({
Tags: [],
});
});

it('creates no SNS topics', async () => {
Expand All @@ -73,6 +81,9 @@ describe('AWSSNSTopicProvider', () => {
} as Partial<Topic> as any,
],
});
sns.on(ListTagsForResourceCommand).resolves({
Tags: [],
});
});

it('creates SNS topic entities', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ export class AWSSNSTopicProvider extends AWSEntityProvider {
for await (const topicPage of topicPages) {
for (const topic of topicPage.Topics || []) {
if (topic.TopicArn) {
const tagsResponse = await sns.listTagsForResource({
ResourceArn: topic.TopicArn,
});
const tags = tagsResponse.Tags ?? [];
const topicName = topic.TopicArn.split(':').pop() || 'unknown-topic';
const consoleLink = new ARN(topic.TopicArn).consoleLink;
const topicEntity: ResourceEntity = {
Expand All @@ -110,12 +114,12 @@ export class AWSSNSTopicProvider extends AWSEntityProvider {
},
name: topicName,
title: topicName,
labels: {}, // Add any labels if necessary
labels: this.labelsFromTags(tags),
},
spec: {
type: 'aws-sns-topic',
owner: ownerFromTags([], this.getOwnerTag(), groups),
...relationshipsFromTags([]),
owner: ownerFromTags(tags, this.getOwnerTag(), groups),
...relationshipsFromTags(tags),
},
};

Expand Down
Loading

0 comments on commit d8b3b4f

Please sign in to comment.