A command-line tool which can move CloudFormation resources between stacks

Overview

cfn-teleport

Release crates.io License

A command-line tool which can move CloudFormation resources between stacks.

Demo

Installation

On a Mac you can install via Homebrew:

brew install udondan/software/cfn-teleport

Pre-compiled binaries for various operating systems and architectures are available for download.

If you have rust/cargo installed, you can simple install the crate:

cargo install cfn-teleport

Usage

$ cfn-teleport --help
Move CloudFormation resources between stacks

Usage: cfn-teleport [OPTIONS]

Options:
  -s, --source <SOURCE>         Name of the source stack
  -t, --target <TARGET>         Name of the target stack
  -r, --resource <ID[:NEW_ID]>  Logical ID of a resource from the source stack - optionally with a new ID for the target stack
  -y, --yes                     Automatically confirm all prompts
  -h, --help                    Print help
  -V, --version                 Print version

Example usage:

cfn-teleport --source Stack1 --target Stack2 --resource Bucket21D68F7E8 --resource Bucket182C536A1 --yes

If any of the required options is undefined, the program will ask for it during execution.

Contributing

Contributions are welcome!

This project uses conventional commits. Please make sure all your merge request titles follow these specifications.

Comments
  • chore(deps): bump aws-cdk-lib from 2.68.0 to 2.69.0 in /test/cdk

    chore(deps): bump aws-cdk-lib from 2.68.0 to 2.69.0 in /test/cdk

    Bumps aws-cdk-lib from 2.68.0 to 2.69.0.

    Release notes

    Sourced from aws-cdk-lib's releases.

    v2.69.0

    Features

    • custom-resources: AwsCustomResource copy physicalResourceId from request when omit it in onUpdate (#24194) (21ad7a7), closes #23843
    • docdb: added ability to enable performance insights (#24039) (c897f44), closes #24036
    • ecr-assets: Support cache-from and cache-to flags (#24024) (4e02566)
    • eks: support for Kubernetes version 1.25 (#24484) (70fd3e9), closes #24282
    • rds: add support for minor versions of PostgreSQL: 14.7, 13.10, 12.14, and 11.19 (#24539) (15cb919)
    • rds: PostgreSQL engine version 15.2 (#24463) (59d795b), closes #24462

    Bug Fixes

    • custom-resource: custom resources fail with data containing multi-byte utf8 chars (#24501) (9bd5078), closes #24491
    • ecr-assets: prefix cache arguments correctly (#24524) (d451b30)
    • pipelines: Ubuntu 5 images will be slow, move to Ubuntu 6 (#24544) (1f62c43)
    • sfn: can't override toStateJson() from other languages (#24593) (e955d18), closes #14639

    Alpha modules (2.69.0-alpha.0)

    Features

    Changelog

    Sourced from aws-cdk-lib's changelog.

    2.69.0 (2023-03-14)

    Features

    • custom-resources: AwsCustomResource copy physicalResourceId from request when omit it in onUpdate (#24194) (21ad7a7), closes #23843
    • docdb: added ability to enable performance insights (#24039) (c897f44), closes #24036
    • ecr-assets: Support cache-from and cache-to flags (#24024) (4e02566)
    • eks: support for Kubernetes version 1.25 (#24484) (70fd3e9), closes #24282
    • rds: add support for minor versions of PostgreSQL: 14.7, 13.10, 12.14, and 11.19 (#24539) (15cb919)
    • rds: PostgreSQL engine version 15.2 (#24463) (59d795b), closes #24462

    Bug Fixes

    • custom-resource: custom resources fail with data containing multi-byte utf8 chars (#24501) (9bd5078), closes #24491
    • ecr-assets: prefix cache arguments correctly (#24524) (d451b30)
    • pipelines: Ubuntu 5 images will be slow, move to Ubuntu 6 (#24544) (1f62c43)
    • sfn: can't override toStateJson() from other languages (#24593) (e955d18), closes #14639
    Commits

    Dependabot compatibility score

    You can trigger a rebase of this PR by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies javascript 
    opened by dependabot[bot] 2
  • chore(deps): bump constructs from 10.1.276 to 10.1.283 in /test/cdk

    chore(deps): bump constructs from 10.1.276 to 10.1.283 in /test/cdk

    Bumps constructs from 10.1.276 to 10.1.283.

    Release notes

    Sourced from constructs's releases.

    v10.1.283

    10.1.283 (2023-03-20)

    v10.1.282

    10.1.282 (2023-03-19)

    v10.1.281

    10.1.281 (2023-03-18)

    v10.1.280

    10.1.280 (2023-03-17)

    v10.1.279

    10.1.279 (2023-03-16)

    v10.1.278

    10.1.278 (2023-03-15)

    v10.1.277

    10.1.277 (2023-03-14)

    Commits

    Dependabot compatibility score

    You can trigger a rebase of this PR by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies javascript 
    opened by dependabot[bot] 2
  • chore(deps): bump @types/node from 18.15.1 to 18.15.3 in /test/cdk

    chore(deps): bump @types/node from 18.15.1 to 18.15.3 in /test/cdk

    Bumps @types/node from 18.15.1 to 18.15.3.

    Commits

    Dependabot compatibility score

    You can trigger a rebase of this PR by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies javascript 
    opened by dependabot[bot] 2
  • chore(deps): bump clap from 4.1.13 to 4.1.14

    chore(deps): bump clap from 4.1.13 to 4.1.14

    Bumps clap from 4.1.13 to 4.1.14.

    Release notes

    Sourced from clap's releases.

    v4.1.14

    [4.1.14] - 2023-03-28

    Features

    • (derive) #[group] raw attribute support

    Performance

    • (derive) clap_builder was pulled out of clap so it could build in parallel to clap_derive
    • os_str_bytes dependency was removed for faster builds and smaller binaries
    Changelog

    Sourced from clap's changelog.

    [4.1.14] - 2023-03-28

    Features

    • (derive) #[group] raw attribute support

    Performance

    • (derive) clap_builder was pulled out of clap so it could build in parallel to clap_derive
    • os_str_bytes dependency was removed for faster builds and smaller binaries
    Commits

    Dependabot compatibility score

    You can trigger a rebase of this PR by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies rust 
    opened by dependabot[bot] 1
  • chore(main): release 0.3.0

    chore(main): release 0.3.0

    :robot: I have created a release beep boop

    0.3.0 (2023-03-30)

    Features

    • validating all templates before execution and optimize output (f6b88c5)

    Bug Fixes

    • adds all capabilities to the changeset, so we can process all possible resources and templates (2f7e39f)
    • adds DeletionPolicy to all resources as required by CFN import (4b25a57)
    • select correct (first) resource identifier, for resources that have multiple possible identifier keys (9e9e628)

    Reverts

    • for now, disable renaming of resources (0f7a8db)

    This PR was generated with Release Please. See documentation.

    autorelease: tagged 
    opened by udondan 1
  • chore(main): release 0.2.0

    chore(main): release 0.2.0

    :robot: I have created a release beep boop

    0.2.0 (2023-03-26)

    Features

    • Adds spinner when waiting for CFN actions (#61) (8025a7f)
    • improves output formatting (#65) (c2b38f6)

    Bug Fixes

    • use pagination to get all stacks (#59) (6e5053b)

    This PR was generated with Release Please. See documentation.

    autorelease: tagged 
    opened by udondan 1
  • chore(main): release 0.1.1

    chore(main): release 0.1.1

    opened by udondan 1
  • chore(deps): bump typescript from 4.9.5 to 5.0.2 in /test/cdk

    chore(deps): bump typescript from 4.9.5 to 5.0.2 in /test/cdk

    Bumps typescript from 4.9.5 to 5.0.2.

    Release notes

    Sourced from typescript's releases.

    TypeScript 5.0

    For release notes, check out the release announcement.

    For new features, check out the What's new in TypeScript v5.0.2.

    For the complete list of fixed issues, check out the

    Downloads are available on:

    TypeScript 5.0 RC

    For release notes, check out the release announcement.

    TypeScript 5.0 Beta

    For release notes, check out the release announcement.

    For the complete list of fixed issues, check out the

    Downloads are available on:

    Commits
    • 3ec598c Update LKG
    • 0e765ac 🤖 Pick PR #53268 (fix(53204): Bug: __runInitializers(...) into release-5.0 (#...
    • cb69c8a Update LKG
    • d97bb67 🤖 Pick PR #53174 (Remove old references to Node v4, s...) into release-5.0 (#...
    • 6e59874 🤖 Pick PR #53240 (Allow 'verbatimModuleSyntax' with t...) into release-5.0 (#...
    • 9a8badd Bump version to 5.0.2 and LKG
    • a5484ae 🤖 Pick PR #53139 (Make ModuleResolutionKind.Node10 ch...) into release-5.0 (#...
    • 23455b4 Cherry-pick #52993 to release-5.0 (#53142)
    • f7f44da 🤖 Pick PR #53183 (Set package.json minimum to Node 12...) into release-5.0 (#...
    • 4d4227a Pin dependencies in release-5.0 (#53126)
    • Additional commits viewable in compare view

    Dependabot compatibility score

    You can trigger a rebase of this PR by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies javascript 
    opened by dependabot[bot] 1
  • chore(deps): bump @types/node from 17.0.18 to 18.15.1 in /test/cdk

    chore(deps): bump @types/node from 17.0.18 to 18.15.1 in /test/cdk

    Bumps @types/node from 17.0.18 to 18.15.1.

    Commits

    Dependabot compatibility score

    You can trigger a rebase of this PR by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies javascript 
    opened by dependabot[bot] 1
  • chore(main): release 0.1.0

    chore(main): release 0.1.0

    :robot: I have created a release beep boop

    0.1.0 (2023-03-12)

    Features

    • now usable via command line options (#32) (5fce44f)

    This PR was generated with Release Please. See documentation.

    autorelease: tagged 
    opened by udondan 1
  • Should support non-interactively mode

    Should support non-interactively mode

    Currently the tool can only work interactively, the user has to provide input at runtime.

    The tool should also support command line args, e.g.

    cdn-resource-mirator \
      --source A \
      --target B \
      -y \
      --resource Bucket182C536A1 \
      --resource Bucket21D68F7E8
    
    opened by udondan 1
  • chore(deps): bump aws-sdk-cloudformation from 0.24.0 to 0.25.0

    chore(deps): bump aws-sdk-cloudformation from 0.24.0 to 0.25.0

    Bumps aws-sdk-cloudformation from 0.24.0 to 0.25.0.

    Changelog

    Sourced from aws-sdk-cloudformation's changelog.

    March 30th, 2023

    Breaking Changes:

    • ⚠🎉 (smithy-rs#2467) Update MSRV to 1.66.1

    • ⚠ (smithy-rs#76, smithy-rs#2129) Request IDs can now be easily retrieved on successful responses. For example, with S3:

      // Import the trait to get the `request_id` method on outputs
      use aws_sdk_s3::types::RequestId;
      let output = client.list_buckets().send().await?;
      println!("Request ID: {:?}", output.request_id());
      
    • ⚠ (smithy-rs#76, smithy-rs#2129) Retrieving a request ID from errors now requires importing the RequestId trait. For example, with S3:

      use aws_sdk_s3::types::RequestId;
      println!("Request ID: {:?}", error.request_id());
      
    • ⚠ (smithy-rs#76, smithy-rs#2129) The message() and code() methods on errors have been moved into ProvideErrorMetadata trait. This trait will need to be imported to continue calling these.

    • ⚠ (smithy-rs#76, smithy-rs#2129, smithy-rs#2075) The *Error and *ErrorKind types have been combined to make error matching simpler.

      Before:

      let result = client
          .get_object()
          .bucket(BUCKET_NAME)
          .key("some-key")
          .send()
          .await;
      match result {
          Ok(_output) => { /* Do something with the output */ }
          Err(err) => match err.into_service_error() {
              GetObjectError { kind, .. } => match kind {
                  GetObjectErrorKind::InvalidObjectState(value) => println!("invalid object state: {:?}", value),
                  GetObjectErrorKind::NoSuchKey(_) => println!("object didn't exist"),
              }
              err @ GetObjectError { .. } if err.code() == Some("SomeUnmodeledError") => {}
              err @ _ => return Err(err.into()),
          },
      }
      

      After:

      // Needed to access the `.code()` function on the error type:
      use aws_sdk_s3::types::ProvideErrorMetadata;
      let result = client
          .get_object()
          .bucket(BUCKET_NAME)
          .key("some-key")
      

    ... (truncated)

    Commits

    Dependabot compatibility score

    You can trigger a rebase of this PR by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    opened by dependabot[bot] 0
  • Remove DeletionPolicy

    Remove DeletionPolicy

    When we import resources, we have to add a DeletionPolicy to all imported resources.

    After importing, we should remove the DeletionPolicy. For this to happen, we have to store the resources where we added the DeletionPolicy during import, since we don"t want to remove DeletionPolicies which have been already set before importing.

    enhancement 
    opened by udondan 0
  • In case of import error, save template to disk

    In case of import error, save template to disk

    In case the import fails, we should save the template to disk, so the user can inspect the tempalte and use it for manual import.

    We then also can implement a --retry option, which will take the template and proceed.

    enhancement 
    opened by udondan 0
  • Enable renaming of resources

    Enable renaming of resources

    Renaming is implemented but commented out in the code.

    Currently renaming is too dangerous, as have have not implemented checking for references to the renamed resource. In case the resource is renamed, all references need to be updated.

    enhancement 
    opened by udondan 0
Releases(v0.3.0)
Owner
Daniel Schroeder
Software Engineer @dbsystel
Daniel Schroeder
A command-line tool collection to assist development written in RUST

dtool dtool is a command-line tool collection to assist development Table of Contents Description Usage Tips Installation Description Now dtool suppor

GB 314 Dec 18, 2022
A cross platform tool which instantly notifies about COVID vaccine availability.

?? CoWIN Notifier ?? A cross-platform tool written in rust, which instantly notifies users about COVID-19 vaccine availability at their regions. Curre

Sanskar Jaiswal 20 May 20, 2021
Command line interface to manage clipboard

cb Command line interface to manage clipboard How to install Pre-Compiled you can download a pre-compiled executable, then you should copy that execut

Navid 74 Dec 18, 2022
A Command Line OTP Authenticator application.

cloak A Command Line OTP (One Time Password) Authenticator application written in Rust that generates time-based and counter-based OTP codes. Motivati

Evans Murithi 205 Jan 5, 2023
Rs.aws-login - A command line utility to simplify logging into AWS services.

aws-login A command line utility to simplify logging into AWS accounts and services. $ aws-login use ? Please select a profile to use: › ❯ dev-read

Kevin Herrera 11 Oct 30, 2022
Transfer data with the LCU in the command-line interface! 🖥

llux llux (short for LCU Lux) is an open-source CLI tool to easily transfer data with the LCU without any script or code setup, hehe! Preview Download

Blossomi Shymae 5 Jul 30, 2023
A lean, minimal, and stable set of types for color interoperation between crates in Rust.

This library provides a lean, minimal, and stable set of types for color interoperation between crates in Rust. Its goal is to serve the same function that mint provides for (linear algebra) math types.

Gray Olson 16 Sep 21, 2022
Get a diff between two OpenAPI descriptions.

Get the difference between two OpenAPI descriptions.

Marc-Andre Giroux 25 Aug 22, 2022
Easy switch between AWS Profiles and Regions

AWSP - CLI To Manage your AWS Profiles! AWSP provides an interactive terminal to interact with your AWS Profiles. The aim of this project is to make i

KubeOps Skills 14 Dec 25, 2022
This crate bridges between gstreamer and tracing ecosystems.

This crate provides a bridge between gstreamer and the tracing ecosystem. The goal is to allow Rust applications utilizing GStreamer to better integra

Standard Cognition OSS 17 Jun 7, 2022
Simple interoperability between C++ coroutines and asynchronous Rust

cxx-async Overview cxx-async is a Rust crate that extends the cxx library to provide seamless interoperability between asynchronous Rust code using as

Patrick Walton 180 Dec 16, 2022
my attempt at compromise between unwrapping and bullying my dependencies' authors for Error impl

string-eyre Has this happened to you? error[E0599]: the method `wrap_err` exists for enum `Result<(), tauri::Error>`, but its trait bounds were not sa

Michał Sidor 1 Nov 25, 2021
A compatibility layer to smooth the transition between different versions of embedded-hal

Embedded HAL Compatibility Layer A compatibility layer to smooth the transition between different versions of embedded-hal (specifically 0.2.x and 1.0

Ryan 7 Sep 11, 2022
Easily sync your clipboard between devices. This is a work in progress app.

Clipboard Sync Description Easily sync your clipboard between devices. This is a work in progress app. Stack Frontend: React Tauri isomorphic-ws TSX,

Steveplays 2 Mar 2, 2022
Count and convert between different indexing schemes on utf8 string slices

Str Indices Count and convert between different indexing schemes on utf8 string slices. The following schemes are currently supported: Chars (or "Unic

Nathan Vegdahl 11 Dec 25, 2022
Generate enum from a trait, with converters between them

Derive macro for Rust that turns traits into enums, providing tools for calling funtions over channels

Vitaly Shukela 16 Nov 3, 2022
A translator interface between VoiceMeeter/VBAN and the X-Touch

VBAN -> XCtrl translator This serves as a network based translator for interfacing the Behringer X-Touch with VoiceMeeter Potato. It is designed to ru

Ollie Nye 4 Sep 3, 2022
Create virtual serial ports, connect them to physical serial ports, and create routes between them all.

Virtual Serial Port Router (vsp-router) Create virtual serial ports, connect them to physical serial ports, and create routes between them all. vsp-ro

Rob Donnelly 3 Nov 24, 2022
Stdto provides a set of functional traits for conversion between various data representations.

Stdto stdto provides a set of functional traits for conversion between various data representations. | Examples | Docs | Latest Note | stdto = "0.13.0

Doha Lee 5 Dec 21, 2022