Design decisions
================

This document captures outcomes and, in some cases, the through process behind
some of the design decisions that took place while architecting CloudBridge.
It is intended as a reference.

Require zone parameter when creating a default subnet
-----------------------------------------------------

  Placement zone is required because it is an explicit application decision,
  even though ideally *default* would not require input. Before requiring it,
  the implementations would create a subnet in each availability zone and return
  the first one in the list. This could potentially return different values over
  time. Another factor influencing the decision was the example of creating a
  volume followed by creating an instance with presumably the two needing to be
  in the same zone. By requiring the zone across the board, it is less likely to
  lead to a mismatch. (Related to 63_.)

Resource identification, naming, and labeling
---------------------------------------------

  While it would be reasonable to expect that complex constructs like
  networking would be the most difficult to abstract away uniformly across
  providers, in retrospect, simple naming of objects has arguably been the most
  complex and convoluted to map consistently. CloudBridge has been through
  several iterations of naming and labeling, before finally settling on the
  current design. This section captures that history and design rationale.

  **First iteration**
  In the early days, when CloudBridge supported only AWS and OpenStack, there
  were only two concepts, `id` and `name`. The `id` was straightforward enough,
  as it usually mapped to a unique identifier, auto-generated by the provider.
  The `name` generally mapped to a tag in the case of AWS, and a `name` field
  in the case of OpenStack. However, even then, there were inconsistencies
  within individual providers. For example, while AWS generally supported tags,
  it had a dedicated name field for machine images called ami-name.
  Furthermore, this name field could only be set at image creation time, and
  could not be changed thereafter. Similarly, AWS does not allow VM firewall
  (i.e., security group) names to be changed. Nevertheless, CloudBridge
  continued to use id and name, with the name being changeable for some
  resources, and read-only in others.

  As CloudBridge evolved and support was added for Azure and GCP, things only
  became more complex. Some providers (e.g. Azure and GCP) used a user-provided
  value instead of an auto-generated value as an `id`, which would also be
  displayed in their respective dashboards as `Name`. This meant that they were
  treating their servers as individually named pets, instead of adopting the
  cattle model, should one be tempted to use that macabre `pets vs cattle`_
  analogy. These user-provided names could not be changed after a resource had
  been created. Instead, these providers seemed to be gravitating toward the
  use of tags (or labels) to support arbitrary naming and name changes. Yet,
  not all resources support tags so CloudBridge could not rely solely on tags.
  Further, tags do not need to be unique across multiple resources, while names
  do (at least for some resources, such as vmfirewalls within a private
  network). Overall, consistency was challenging to achieve with resource
  naming. Therefore, it was decided that CloudBridge would continue to support
  resource renaming to the best extent possible and strike a balance between the
  use of the resource name property and resource tags. However, because of the
  inconsistency in rename functionality across providers, using the rename
  capabilities within CloudBridge would lead to cloud-dependent code (Related to
  131_.) and therefore, the only option was to continue to stick a caveat emptor
  to resource renaming.
  
  **Second iteration**
  However, it soon became apparent that this overloaded terminology was
  continuing to cause confusion. The `id` property in CloudBridge mapped to the
  unchangeable `name` property in Azure and GCP, and the *name* property in
  cloudbridge sometimes mapped to a *tag* in certain providers, and a *name* in
  other providers and they were sometimes read-only, sometimes writable. In an
  attempt to disambiguate these concepts, it was then decided that perhaps
  three concepts were needed - `id`, `display_id`, and `label`. The `id` would
  continue to refer to a unique identifier for a resource and be mapped
  accordingly to the underlying provider. The `display_id` would be a more
  user-friendly version of an id, suitable for display to an end-user and be
  unchangeable, but on rare occasions, not unique. For example, AWS ami-name
  was a `display_id` while the ami-id was an `id`. Similarly, an Azure resource
  name mapped to the `display_id`, since it was an unchangeable, user-friendly
  identifier. Finally, label was a changeable, user-assignable value that would
  be mapped often to a tag on the resource, or the name of the resource, should
  the name be changeable. This clearly disambiguated between unique
  identifiers, user-assignable values and read-only, user-friendly values. At
  object creation, all services would accept a label as an optional parameter.
  If provided, the `display_id` would sometimes be derived from the label by
  appending a uuid to the label, depending on the provider. At other times, it
  would simply map to an id.

  **Third iteration**
  It soon became apparent that some resources like keypairs could not have a
  label at all, yet needed to be named during object creation. However, we
  could not use `display_id` for this purpose became the display_id, by
  definition, is unchangeable. It could not be called `label` because the label,
  in contrast, was changeable. Therefore, it seemed like we were back to
  calling it `name` instead, introducing yet a fourth term. To simplify this,
  it was then decided that `display_id` and `name` would be collapsed together
  into one term and be called `name` instead. All resources would have an `id`
  and a `name`, and resources that support it would have a `label`. To make
  things even simpler and consistent, it was also decided that label would be
  made mandatory for all resources during object creation, and follow the same
  restrictions as name, which is to have a 3 character minimum. (This was to
  deal with an exception in OpenStack, where the label mapped to instance name,
  but could not be empty. Therefore, by making all labels mandatory and adhere
  to minimum length restrictions, we could make the overall conventions uniform
  across all resources and therefore easier to remember and enforce.)

  **TL;DR**
  CloudBridge has three concepts when it comes to naming and identifying
  objects:

    - `id` is a unique identifier for an object, always
      auto-generated;
    - `name` is a read-only, user-friendly value which is
      suitable for display to the end-user;
    - `label` is a user-assignable value that can be changed.

  The `name` is often derived from the `label` but not
  always. Not all resources support `labels`. Some only accept `names`, which
  can be specified at object creation time (e.g. keypairs). Both `names` and
  `labels` adhere to the same restrictions - a minimum length of 3 which
  should be alphanumeric characters or dashes only. Names or labels should
  not begin or end with a dash, or have consecutive dashes.

.. _single-zone-provider:

Make providers single zone
---------------------------

  Allowing each operation to specify its own zone led to various complications,
  such as the one detailed above. Ultimately, it led to an impasse with GCP,
  which tended to require the zone for almost every operation and some of our
  methods were not geared to do so. Therefore, by making the provider zone
  specific, we have removed a considerable amount of complexity from the
  code, with no significant impact on usability, since operations generally
  tend to be confined to the same zone. Multi-zone operations now require
  multiple cloud provider instances.

  .. _63: https://github.com/CloudVE/cloudbridge/issues/63
  .. _131: https://github.com/CloudVE/cloudbridge/issues/131
  .. _pets vs cattle: http://cloudscaling.com/blog/cloud-computing/the-history-of-pets-vs-cattle/
