Super excited for what we have coming in 2023!

With cloud native, one of the major challenges is observability and being able to debug production issues quickly. But you can’t really debug your app while it’s being used by users in real time.

It’s nice to have a temporary environment that is as close to production as possible, but spinning up and tearing down a cloud infrastructure quickly is a major pain for developers.

One of the cool features we just shipped at Oatfin is the ability to clone an infrastructure or environment one-to-one to make it easy to reproduce and troubleshoot production problems.

Oatfin UI showing the clone operation

In solving this problem, it would have been nice to have a COPY or CLONE operation in REST. Something I think is fundamental to almost every API.

For now I’m doing:

POST /resource?source=id

If the “source” parameter is present as a query parameter, then it’s a clone operation, otherwise it’s a create operation. The operation is not idempotent meaning it will create a new copy each time the API is called.

Here is what this looks like. For the frontend, I’m using React, Typescript with a tool called umijs and antdesign from Ant financial:

Create request

import { request } from 'umi';

export async function createApp(params) {
  return request('/v1/apps', {
    method: 'POST',
    data: params,
    headers: {
      Authorization: 'Bearer ACCESS_TOKEN,
    },
  })
}

Clone request

import { request } from 'umi';

export async function cloneApp(params, id) {
  return request(`/v1/apps?source=${id}`, {
    method: 'POST',
    data: params,
    headers: {
      Authorization: 'Bearer ACCESS_TOKEN,
    },
  })
}

Calling these functions inside the React component:

export const AppComponent: FC<Props> = (props) => {
    ...
    const handleCreate = async (values) => {
        const res = await createApp(values);
        ...
    };

    const handleClone = async (values) => {
        const res = await cloneApp(values);
        ...
    };

    return (
        <>
            <CreateModal
                ...
                onSubmit={handleCreate}
            />
            <CloneModal
                ...
                onSubmit={handleClone}
            />
        </>
  )
}

The Python & Flask code skeleton:

@api.route('/apps', methods=['POST'])
@jwt_required()
def create_clone_app():

    req_data = flask.request.get_json()
    clone_source = flask.request.args.get('source')

    if not clone_source:
        app = AppsService().create(...)
    else:
        app = AppsService().clone(...)

    return flask.jsonify(
        app=app.json(), 
        message='success',
    ), 200

I’d be interested to see how others deal with the CLONE or COPY in REST.