scikit-learn cython Tips for developing with Cython in scikit learn Cython Best Practices Conventions and Knowledge This documents tips to develop Cython code in scikit learn

Answer:
.. _cython:

Cython Best Practices, Conventions and Knowledge
================================================

This documents tips to develop Cython code in scikit-learn.

Tips for developing with Cython in scikit-learn
-----------------------------------------------

Tips to ease development
^^^^^^^^^^^^^^^^^^^^^^^^

* Time spent reading `Cython's documentation <https://cython.readthedocs.io/en/latest/>`_ is not time lost.

* If you intend to use OpenMP: On MacOS, system's distribution of ``clang`` does not implement OpenMP.
  You can install the ``compilers`` package available on ``conda-forge`` which comes with an implementation of OpenMP.

* Activating `checks <https://github.com/scikit-learn/scikit-learn/blob/62a017efa047e9581ae7df8bbaa62cf4c0544ee4/sklearn/_build_utils/__init__.py#L68-L87>`_ might help. E.g. for activating boundscheck use:

  .. code-block:: bash

         export SKLEARN_ENABLE_DEBUG_CYTHON_DIRECTIVES=1

* `Start from scratch in a notebook <https://cython.readthedocs.io/en/latest/src/quickstart/build.html#using-the-jupyter-notebook>`_ to understand how to use Cython and to get feedback on your work quickly.
  If you plan to use OpenMP for your implementations in your Jupyter Notebook, do add extra compiler and linkers arguments in the Cython magic.

  .. code-block:: python

         # For GCC and for clang
         %%cython --compile-args=-fopenmp --link-args=-fopenmp
         # For Microsoft's compilers
         %%cython --compile-args=/openmp --link-args=/openmp

* To debug C code (e.g. a segfault), do use ``gdb`` with:

  .. code-block:: bash

         gdb --ex r --args python ./entrypoint_to_bug_reproducer.py

* To have access to some value in place to debug in ``cdef (nogil)`` context, use:

  .. code-block:: cython

         with gil:
             print(state_to_print)

* Note that Cython cannot parse f-strings with ``{var=}`` expressions, e.g.

  .. code-block:: bash

         print(f"{test_val=}")

* scikit-learn codebase has a lot of non-unified (fused) types (re)definitions.
  There currently is `ongoing work to simplify and unify that across the codebase
  <https://github.com/scikit-learn/scikit-learn/issues/25572>`_.
  For now, make sure you understand which concrete types are used ultimately.

* You might find this alias to compile individual Cython extension handy:

  .. code-block::

      # You might want to add this alias to your shell script config.
      alias cythonX="cython -X language_level=3 -X boundscheck=False -X wraparound=False -X initializedcheck=False -X nonecheck=False -X cdivision=True"

      # This generates `source.c` as if you had recompiled scikit-learn entirely.
      cythonX --annotate source.pyx

* Using the ``--annotate`` option with this flag allows generating a HTML report of code annotation.
  This report indicates interactions with the CPython interpreter on a line-by-line basis.
  Interactions with the CPython interpreter must be avoided as much as possible in
  the computationally intensive sections of the algorithms.
  For more information, please refer to `this section of Cython's tutorial <https://cython.readthedocs.io/en/latest/src/tutorial/cython_tutorial.html#primes>`_

  .. code-block::

      # This generates a HTML report (`source.html`) for `source.c`.
      cythonX --annotate source.pyx

Tips for performance
^^^^^^^^^^^^^^^^^^^^

* Understand the GIL in context for CPython (which problems it solves, what are its limitations)
  and get a good understanding of when Cython will be mapped to C code free of interactions with
  CPython, when it will not, and when it cannot (e.g. presence of interactions with Python
  objects, which include functions). In this regard, `PEP073 <https://peps.python.org/pep-0703/>`_
  provides a good overview and context and pathways for removal.

* Make sure you have deactivated `checks <https://github.com/scikit-learn/scikit-learn/blob/62a017efa047e9581ae7df8bbaa62cf4c0544ee4/sklearn/_build_utils/__init__.py#L68-L87>`_.

* Always prefer memoryviews instead over ``cnp.ndarray`` when possible: memoryviews are lightweight.

* Avoid memoryview slicing: memoryview slicing might be costly or misleading in some cases and
  we better not use it, even if handling fewer dimensions in some context would be preferable.

* Decorate final classes or methods with ``@final`` (this allows removing virtual tables when needed)

* Inline methods and function when it makes sense

* In doubt, read the generated C or C++ code if you can: "The fewer C instructions and indirections
  for a line of Cython code, the better" is a good rule of thumb.

* ``nogil`` declarations are just hints: when declaring the ``cdef`` functions
  as nogil, it means that they can be called without holding the GIL, but it does not release
  the GIL when entering them. You have to do that yourself either by passing ``nogil=True`` to
  ``cython.parallel.prange`` explicitly, or by using an explicit context manager:

  .. code-block:: cython

      cdef inline void my_func(self) nogil:

          # Some logic interacting with CPython, e.g. allocating arrays via NumPy.

          with nogil:
              # The code here is run as is it were written in C.

          return 0

  This item is based on `this comment from Stéfan's Benhel <https://github.com/cython/cython/issues/2798#issuecomment-459971828>`_

* Direct calls to BLAS routines are possible via interfaces defined in ``sklearn.utils._cython_blas``.

Using OpenMP
^^^^^^^^^^^^

Since scikit-learn can be built without OpenMP, it's necessary to protect each
direct call to OpenMP.

The `_openmp_helpers` module, available in
`sklearn/utils/_openmp_helpers.pyx <https://github.com/scikit-learn/scikit-learn/blob/main/sklearn/utils/_openmp_helpers.pyx>`_
provides protected versions of the OpenMP routines. To use OpenMP routines, they
must be ``cimported`` from this module and not from the OpenMP library directly:

.. code-block:: cython

   from sklearn.utils._openmp_helpers cimport omp_get_max_threads
   max_threads = omp_get_max_threads()

The parallel loop, `prange`, is already protected by cython and can be used directly
from `cython.parallel`.

Types
~~~~~

Cython code requires to use explicit types. This is one of the reasons you get a
performance boost. In order to avoid code duplication, we have a central place
for the most used types in
`sklearn/utils/_typedefs.pyd <https://github.com/scikit-learn/scikit-learn/blob/main/sklearn/utils/_typedefs.pyd>`_.
Ideally you start by having a look there and `cimport` types you need, for example

.. code-block:: cython

    from sklear.utils._typedefs cimport float32, float64

cython   Cython Best Practices  Conventions and Knowledge                                                   This documents tips to develop Cython code in scikit learn   Tips for developing with Cython in scikit learn                                                  Tips to ease development                             Time spent reading  Cython s documentation  https   cython readthedocs io en latest     is not time lost     If you intend to use OpenMP  On MacOS  system s distribution of   clang   does not implement OpenMP    You can install the   compilers   package available on   conda forge   which comes with an implementation of OpenMP     Activating  checks  https   github com scikit learn scikit learn blob 62a017efa047e9581ae7df8bbaa62cf4c0544ee4 sklearn  build utils   init   py L68 L87    might help  E g  for activating boundscheck use        code block   bash           export SKLEARN ENABLE DEBUG CYTHON DIRECTIVES 1     Start from scratch in a notebook  https   cython readthedocs io en latest src quickstart build html using the jupyter notebook    to understand how to use Cython and to get feedback on your work quickly    If you plan to use OpenMP for your implementations in your Jupyter Notebook  do add extra compiler and linkers arguments in the Cython magic        code block   python             For GCC and for clang            cython   compile args  fopenmp   link args  fopenmp            For Microsoft s compilers            cython   compile args  openmp   link args  openmp    To debug C code  e g  a segfault   do use   gdb   with        code block   bash           gdb   ex r   args python   entrypoint to bug reproducer py    To have access to some value in place to debug in   cdef  nogil    context  use        code block   cython           with gil               print state to print     Note that Cython cannot parse f strings with    var     expressions  e g        code block   bash           print f  test val        scikit learn codebase has a lot of non unified  fused  types  re definitions    There currently is  ongoing work to simplify and unify that across the codebase    https   github com scikit learn scikit learn issues 25572       For now  make sure you understand which concrete types are used ultimately     You might find this alias to compile individual Cython extension handy        code block            You might want to add this alias to your shell script config        alias cythonX  cython  X language level 3  X boundscheck False  X wraparound False  X initializedcheck False  X nonecheck False  X cdivision True           This generates  source c  as if you had recompiled scikit learn entirely        cythonX   annotate source pyx    Using the     annotate   option with this flag allows generating a HTML report of code annotation    This report indicates interactions with the CPython interpreter on a line by line basis    Interactions with the CPython interpreter must be avoided as much as possible in   the computationally intensive sections of the algorithms    For more information  please refer to  this section of Cython s tutorial  https   cython readthedocs io en latest src tutorial cython tutorial html primes          code block            This generates a HTML report   source html   for  source c         cythonX   annotate source pyx  Tips for performance                         Understand the GIL in context for CPython  which problems it solves  what are its limitations    and get a good understanding of when Cython will be mapped to C code free of interactions with   CPython  when it will not  and when it cannot  e g  presence of interactions with Python   objects  which include functions   In this regard   PEP073  https   peps python org pep 0703       provides a good overview and context and pathways for removal     Make sure you have deactivated  checks  https   github com scikit learn scikit learn blob 62a017efa047e9581ae7df8bbaa62cf4c0544ee4 sklearn  build utils   init   py L68 L87        Always prefer memoryviews instead over   cnp ndarray   when possible  memoryviews are lightweight     Avoid memoryview slicing  memoryview slicing might be costly or misleading in some cases and   we better not use it  even if handling fewer dimensions in some context would be preferable     Decorate final classes or methods with    final    this allows removing virtual tables when needed     Inline methods and function when it makes sense    In doubt  read the generated C or C   code if you can   The fewer C instructions and indirections   for a line of Cython code  the better  is a good rule of thumb       nogil   declarations are just hints  when declaring the   cdef   functions   as nogil  it means that they can be called without holding the GIL  but it does not release   the GIL when entering them  You have to do that yourself either by passing   nogil True   to     cython parallel prange   explicitly  or by using an explicit context manager        code block   cython        cdef inline void my func self  nogil               Some logic interacting with CPython  e g  allocating arrays via NumPy             with nogil                  The code here is run as is it were written in C             return 0    This item is based on  this comment from St fan s Benhel  https   github com cython cython issues 2798 issuecomment 459971828       Direct calls to BLAS routines are possible via interfaces defined in   sklearn utils  cython blas     Using OpenMP               Since scikit learn can be built without OpenMP  it s necessary to protect each direct call to OpenMP   The   openmp helpers  module  available in  sklearn utils  openmp helpers pyx  https   github com scikit learn scikit learn blob main sklearn utils  openmp helpers pyx    provides protected versions of the OpenMP routines  To use OpenMP routines  they must be   cimported   from this module and not from the OpenMP library directly      code block   cython     from sklearn utils  openmp helpers cimport omp get max threads    max threads   omp get max threads     The parallel loop   prange   is already protected by cython and can be used directly from  cython parallel    Types        Cython code requires to use explicit types  This is one of the reasons you get a performance boost  In order to avoid code duplication  we have a central place for the most used types in  sklearn utils  typedefs pyd  https   github com scikit learn scikit learn blob main sklearn utils  typedefs pyd     Ideally you start by having a look there and  cimport  types you need  for example     code block   cython      from sklear utils  typedefs cimport float32  float64


scikit-learn The is important to the communication in the project it helps priorities For this reason it is important to curate it adding labels bugtriaging to issues and closing issues that are not necessary developers identify major projects to work on as well as to discuss Bug triaging and issue curation

Answer:
.. _bug_triaging:

Bug triaging and issue curation
===============================

The `issue tracker <https://github.com/scikit-learn/scikit-learn/issues>`_
is important to the communication in the project: it helps
developers identify major projects to work on, as well as to discuss
priorities. For this reason, it is important to curate it, adding labels
to issues and closing issues that are not necessary.

Working on issues to improve them
---------------------------------

Improving issues increases their chances of being successfully resolved.
Guidelines on submitting good issues can be found :ref:`here
<filing_bugs>`.
A third party can give useful feedback or even add
comments on the issue.
The following actions are typically useful:

- documenting issues that are missing elements to reproduce the problem
  such as code samples

- suggesting better use of code formatting

- suggesting to reformulate the title and description to make them more
  explicit about the problem to be solved

- linking to related issues or discussions while briefly describing how
  they are related, for instance "See also #xyz for a similar attempt
  at this" or "See also #xyz where the same thing happened in
  SomeEstimator" provides context and helps the discussion.

.. topic:: Fruitful discussions

   Online discussions may be harder than it seems at first glance, in
   particular given that a person new to open-source may have a very
   different understanding of the process than a seasoned maintainer.

   Overall, it is useful to stay positive and assume good will. `The
   following article
   <https://gael-varoquaux.info/programming/technical-discussions-are-hard-a-few-tips.html>`_
   explores how to lead online discussions in the context of open source.

Working on PRs to help review
-----------------------------

Reviewing code is also encouraged. Contributors and users are welcome to
participate to the review process following our :ref:`review guidelines
<code_review>`.

Triaging operations for members of the core and contributor experience teams
----------------------------------------------------------------------------

In addition to the above, members of the core team and the contributor experience team
can do the following important tasks:

- Update :ref:`labels for issues and PRs <issue_tracker_tags>`: see the list of
  the `available github labels
  <https://github.com/scikit-learn/scikit-learn/labels>`_.

- :ref:`Determine if a PR must be relabeled as stalled <stalled_pull_request>`
  or needs help (this is typically very important in the context
  of sprints, where the risk is to create many unfinished PRs)

- If a stalled PR is taken over by a newer PR, then label the stalled PR as
  "Superseded", leave a comment on the stalled PR linking to the new PR, and
  likely close the stalled PR.

- Triage issues:

  - **close usage questions** and politely point the reporter to use
    Stack Overflow instead.

  - **close duplicate issues**, after checking that they are
    indeed duplicate. Ideally, the original submitter moves the
    discussion to the older, duplicate issue

  - **close issues that cannot be replicated**, after leaving time (at
    least a week) to add extra information

:ref:`Saved replies <saved_replies>` are useful to gain time and yet be
welcoming and polite when triaging.

See the github description for `roles in the organization
<https://docs.github.com/en/github/setting-up-and-managing-organizations-and-teams/repository-permission-levels-for-an-organization>`_.

.. topic:: Closing issues: a tough call

    When uncertain on whether an issue should be closed or not, it is
    best to strive for consensus with the original poster, and possibly
    to seek relevant expertise. However, when the issue is a usage
    question, or when it has been considered as unclear for many years it
    should be closed.

A typical workflow for triaging issues
--------------------------------------

The following workflow [1]_ is a good way to approach issue triaging:

#. Thank the reporter for opening an issue

   The issue tracker is many people's first interaction with the
   scikit-learn project itself, beyond just using the library. As such,
   we want it to be a welcoming, pleasant experience.

#. Is this a usage question? If so close it with a polite message
   (:ref:`here is an example <saved_replies>`).

#. Is the necessary information provided?

   If crucial information (like the version of scikit-learn used), is
   missing feel free to ask for that and label the issue with "Needs
   info".

#. Is this a duplicate issue?

   We have many open issues. If a new issue seems to be a duplicate,
   point to the original issue. If it is a clear duplicate, or consensus
   is that it is redundant, close it. Make sure to still thank the
   reporter, and encourage them to chime in on the original issue, and
   perhaps try to fix it.

   If the new issue provides relevant information, such as a better or
   slightly different example, add it to the original issue as a comment
   or an edit to the original post.

#. Make sure that the title accurately reflects the issue. If you have the
   necessary permissions edit it yourself if it's not clear.

#. Is the issue minimal and reproducible?

   For bug reports, we ask that the reporter provide a minimal
   reproducible example. See `this useful post
   <https://matthewrocklin.com/blog/work/2018/02/28/minimal-bug-reports>`_
   by Matthew Rocklin for a good explanation. If the example is not
   reproducible, or if it's clearly not minimal, feel free to ask the reporter
   if they can provide and example or simplify the provided one.
   Do acknowledge that writing minimal reproducible examples is hard work.
   If the reporter is struggling, you can try to write one yourself.

   If a reproducible example is provided, but you see a simplification,
   add your simpler reproducible example.

#. Add the relevant labels, such as "Documentation" when the issue is
   about documentation, "Bug" if it is clearly a bug, "Enhancement" if it
   is an enhancement request, ...

   If the issue is clearly defined and the fix seems relatively
   straightforward, label the issue as “Good first issue”.

   An additional useful step can be to tag the corresponding module e.g.
   `sklearn.linear_models` when relevant.

#. Remove the "Needs Triage" label from the issue if the label exists.

.. [1] Adapted from the pandas project `maintainers guide
       <https://pandas.pydata.org/docs/development/maintaining.html>`_

bug triaging   Bug triaging and issue curation                                  The  issue tracker  https   github com scikit learn scikit learn issues    is important to the communication in the project  it helps developers identify major projects to work on  as well as to discuss priorities  For this reason  it is important to curate it  adding labels to issues and closing issues that are not necessary   Working on issues to improve them                                    Improving issues increases their chances of being successfully resolved  Guidelines on submitting good issues can be found  ref  here  filing bugs    A third party can give useful feedback or even add comments on the issue  The following actions are typically useful     documenting issues that are missing elements to reproduce the problem   such as code samples    suggesting better use of code formatting    suggesting to reformulate the title and description to make them more   explicit about the problem to be solved    linking to related issues or discussions while briefly describing how   they are related  for instance  See also  xyz for a similar attempt   at this  or  See also  xyz where the same thing happened in   SomeEstimator  provides context and helps the discussion      topic   Fruitful discussions     Online discussions may be harder than it seems at first glance  in    particular given that a person new to open source may have a very    different understanding of the process than a seasoned maintainer      Overall  it is useful to stay positive and assume good will   The    following article     https   gael varoquaux info programming technical discussions are hard a few tips html       explores how to lead online discussions in the context of open source   Working on PRs to help review                                Reviewing code is also encouraged  Contributors and users are welcome to participate to the review process following our  ref  review guidelines  code review     Triaging operations for members of the core and contributor experience teams                                                                               In addition to the above  members of the core team and the contributor experience team can do the following important tasks     Update  ref  labels for issues and PRs  issue tracker tags    see the list of   the  available github labels    https   github com scikit learn scikit learn labels         ref  Determine if a PR must be relabeled as stalled  stalled pull request     or needs help  this is typically very important in the context   of sprints  where the risk is to create many unfinished PRs     If a stalled PR is taken over by a newer PR  then label the stalled PR as    Superseded   leave a comment on the stalled PR linking to the new PR  and   likely close the stalled PR     Triage issues         close usage questions   and politely point the reporter to use     Stack Overflow instead         close duplicate issues    after checking that they are     indeed duplicate  Ideally  the original submitter moves the     discussion to the older  duplicate issue        close issues that cannot be replicated    after leaving time  at     least a week  to add extra information   ref  Saved replies  saved replies   are useful to gain time and yet be welcoming and polite when triaging   See the github description for  roles in the organization  https   docs github com en github setting up and managing organizations and teams repository permission levels for an organization         topic   Closing issues  a tough call      When uncertain on whether an issue should be closed or not  it is     best to strive for consensus with the original poster  and possibly     to seek relevant expertise  However  when the issue is a usage     question  or when it has been considered as unclear for many years it     should be closed   A typical workflow for triaging issues                                         The following workflow  1   is a good way to approach issue triaging      Thank the reporter for opening an issue     The issue tracker is many people s first interaction with the    scikit learn project itself  beyond just using the library  As such     we want it to be a welcoming  pleasant experience      Is this a usage question  If so close it with a polite message      ref  here is an example  saved replies         Is the necessary information provided      If crucial information  like the version of scikit learn used   is    missing feel free to ask for that and label the issue with  Needs    info       Is this a duplicate issue      We have many open issues  If a new issue seems to be a duplicate     point to the original issue  If it is a clear duplicate  or consensus    is that it is redundant  close it  Make sure to still thank the    reporter  and encourage them to chime in on the original issue  and    perhaps try to fix it      If the new issue provides relevant information  such as a better or    slightly different example  add it to the original issue as a comment    or an edit to the original post      Make sure that the title accurately reflects the issue  If you have the    necessary permissions edit it yourself if it s not clear      Is the issue minimal and reproducible      For bug reports  we ask that the reporter provide a minimal    reproducible example  See  this useful post     https   matthewrocklin com blog work 2018 02 28 minimal bug reports       by Matthew Rocklin for a good explanation  If the example is not    reproducible  or if it s clearly not minimal  feel free to ask the reporter    if they can provide and example or simplify the provided one     Do acknowledge that writing minimal reproducible examples is hard work     If the reporter is struggling  you can try to write one yourself      If a reproducible example is provided  but you see a simplification     add your simpler reproducible example      Add the relevant labels  such as  Documentation  when the issue is    about documentation   Bug  if it is clearly a bug   Enhancement  if it    is an enhancement request          If the issue is clearly defined and the fix seems relatively    straightforward  label the issue as  Good first issue       An additional useful step can be to tag the corresponding module e g      sklearn linear models  when relevant      Remove the  Needs Triage  label from the issue if the label exists       1  Adapted from the pandas project  maintainers guide         https   pandas pydata org docs development maintaining html


scikit-learn minimalreproducer Crafting a minimal reproducer for scikit learn question in the discussions being able to craft minimal reproducible examples Whether submitting a bug report designing a suite of tests or simply posting a or minimal workable examples is the key to communicating effectively and

Answer:
.. _minimal_reproducer:

==============================================
Crafting a minimal reproducer for scikit-learn
==============================================

Whether submitting a bug report, designing a suite of tests, or simply posting a
question in the discussions, being able to craft minimal, reproducible examples
(or minimal, workable examples) is the key to communicating effectively and
efficiently with the community.

There are very good guidelines on the internet such as `this StackOverflow
document <https://stackoverflow.com/help/mcve>`_ or `this blogpost by Matthew
Rocklin <https://matthewrocklin.com/blog/work/2018/02/28/minimal-bug-reports>`_
on crafting Minimal Complete Verifiable Examples (referred below as MCVE).
Our goal is not to be repetitive with those references but rather to provide a
step-by-step guide on how to narrow down a bug until you have reached the
shortest possible code to reproduce it.

The first step before submitting a bug report to scikit-learn is to read the
`Issue template
<https://github.com/scikit-learn/scikit-learn/blob/main/.github/ISSUE_TEMPLATE/bug_report.yml>`_.
It is already quite informative about the information you will be asked to
provide.

.. _good_practices:

Good practices
==============

In this section we will focus on the **Steps/Code to Reproduce** section of the
`Issue template
<https://github.com/scikit-learn/scikit-learn/blob/main/.github/ISSUE_TEMPLATE/bug_report.yml>`_.
We will start with a snippet of code that already provides a failing example but
that has room for readability improvement. We then craft a MCVE from it.

**Example**

.. code-block:: python

    # I am currently working in a ML project and when I tried to fit a
    # GradientBoostingRegressor instance to my_data.csv I get a UserWarning:
    # "X has feature names, but DecisionTreeRegressor was fitted without
    # feature names". You can get a copy of my dataset from
    # https://example.com/my_data.csv and verify my features do have
    # names. The problem seems to arise during fit when I pass an integer
    # to the n_iter_no_change parameter.

    df = pd.read_csv('my_data.csv')
    X = df[["feature_name"]] # my features do have names
    y = df["target"]

    # We set random_state=42 for the train_test_split
    X_train, X_test, y_train, y_test = train_test_split(
        X, y, test_size=0.33, random_state=42
    )

    scaler = StandardScaler(with_mean=False)
    X_train = scaler.fit_transform(X_train)
    X_test = scaler.transform(X_test)

    # An instance with default n_iter_no_change raises no error nor warnings
    gbdt = GradientBoostingRegressor(random_state=0)
    gbdt.fit(X_train, y_train)
    default_score = gbdt.score(X_test, y_test)

    # the bug appears when I change the value for n_iter_no_change
    gbdt = GradientBoostingRegressor(random_state=0, n_iter_no_change=5)
    gbdt.fit(X_train, y_train)
    other_score = gbdt.score(X_test, y_test)

    other_score = gbdt.score(X_test, y_test)

Provide a failing code example with minimal comments
----------------------------------------------------

Writing instructions to reproduce the problem in English is often ambiguous.
Better make sure that all the necessary details to reproduce the problem are
illustrated in the Python code snippet to avoid any ambiguity. Besides, by this
point you already provided a concise description in the **Describe the bug**
section of the `Issue template
<https://github.com/scikit-learn/scikit-learn/blob/main/.github/ISSUE_TEMPLATE/bug_report.yml>`_.

The following code, while **still not minimal**, is already **much better**
because it can be copy-pasted in a Python terminal to reproduce the problem in
one step. In particular:

- it contains **all necessary imports statements**;
- it can fetch the public dataset without having to manually download a
  file and put it in the expected location on the disk.

**Improved example**

.. code-block:: python

    import pandas as pd

    df = pd.read_csv("https://example.com/my_data.csv")
    X = df[["feature_name"]]
    y = df["target"]

    from sklearn.model_selection import train_test_split

    X_train, X_test, y_train, y_test = train_test_split(
        X, y, test_size=0.33, random_state=42
    )

    from sklearn.preprocessing import StandardScaler

    scaler = StandardScaler(with_mean=False)
    X_train = scaler.fit_transform(X_train)
    X_test = scaler.transform(X_test)

    from sklearn.ensemble import GradientBoostingRegressor

    gbdt = GradientBoostingRegressor(random_state=0)
    gbdt.fit(X_train, y_train)  # no warning
    default_score = gbdt.score(X_test, y_test)

    gbdt = GradientBoostingRegressor(random_state=0, n_iter_no_change=5)
    gbdt.fit(X_train, y_train)  # raises warning
    other_score = gbdt.score(X_test, y_test)
    other_score = gbdt.score(X_test, y_test)

Boil down your script to something as small as possible
-------------------------------------------------------

You have to ask yourself which lines of code are relevant and which are not for
reproducing the bug. Deleting unnecessary lines of code or simplifying the
function calls by omitting unrelated non-default options will help you and other
contributors narrow down the cause of the bug.

In particular, for this specific example:

- the warning has nothing to do with the `train_test_split` since it already
  appears in the training step, before we use the test set.
- similarly, the lines that compute the scores on the test set are not
  necessary;
- the bug can be reproduced for any value of `random_state` so leave it to its
  default;
- the bug can be reproduced without preprocessing the data with the
  `StandardScaler`.

**Improved example**

.. code-block:: python

    import pandas as pd
    df = pd.read_csv("https://example.com/my_data.csv")
    X = df[["feature_name"]]
    y = df["target"]

    from sklearn.ensemble import GradientBoostingRegressor

    gbdt = GradientBoostingRegressor()
    gbdt.fit(X, y)  # no warning

    gbdt = GradientBoostingRegressor(n_iter_no_change=5)
    gbdt.fit(X, y)  # raises warning

**DO NOT** report your data unless it is extremely necessary
------------------------------------------------------------

The idea is to make the code as self-contained as possible. For doing so, you
can use a :ref:`synth_data`. It can be generated using numpy, pandas or the
:mod:`sklearn.datasets` module. Most of the times the bug is not related to a
particular structure of your data. Even if it is, try to find an available
dataset that has similar characteristics to yours and that reproduces the
problem. In this particular case, we are interested in data that has labeled
feature names.

**Improved example**

.. code-block:: python

    import pandas as pd
    from sklearn.ensemble import GradientBoostingRegressor

    df = pd.DataFrame(
        {
            "feature_name": [-12.32, 1.43, 30.01, 22.17],
            "target": [72, 55, 32, 43],
        }
    )
    X = df[["feature_name"]]
    y = df["target"]

    gbdt = GradientBoostingRegressor()
    gbdt.fit(X, y) # no warning
    gbdt = GradientBoostingRegressor(n_iter_no_change=5)
    gbdt.fit(X, y) # raises warning

As already mentioned, the key to communication is the readability of the code
and good formatting can really be a plus. Notice that in the previous snippet
we:

- try to limit all lines to a maximum of 79 characters to avoid horizontal
  scrollbars in the code snippets blocks rendered on the GitHub issue;
- use blank lines to separate groups of related functions;
- place all the imports in their own group at the beginning.

The simplification steps presented in this guide can be implemented in a
different order than the progression we have shown here. The important points
are:

- a minimal reproducer should be runnable by a simple copy-and-paste in a
  python terminal;
- it should be simplified as much as possible by removing any code steps
  that are not strictly needed to reproducing the original problem;
- it should ideally only rely on a minimal dataset generated on-the-fly by
  running the code instead of relying on external data, if possible.

Use markdown formatting
-----------------------

To format code or text into its own distinct block, use triple backticks.
`Markdown
<https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax>`_
supports an optional language identifier to enable syntax highlighting in your
fenced code block. For example::

    ```python
    from sklearn.datasets import make_blobs

    n_samples = 100
    n_components = 3
    X, y = make_blobs(n_samples=n_samples, centers=n_components)
    ```

will render a python formatted snippet as follows

.. code-block:: python

    from sklearn.datasets import make_blobs

    n_samples = 100
    n_components = 3
    X, y = make_blobs(n_samples=n_samples, centers=n_components)

It is not necessary to create several blocks of code when submitting a bug
report. Remember other reviewers are going to copy-paste your code and having a
single cell will make their task easier.

In the section named **Actual results** of the `Issue template
<https://github.com/scikit-learn/scikit-learn/blob/main/.github/ISSUE_TEMPLATE/bug_report.yml>`_
you are asked to provide the error message including the full traceback of the
exception. In this case, use the `python-traceback` qualifier. For example::

    ```python-traceback
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-1-a674e682c281> in <module>
        4 vectorizer = CountVectorizer(input=docs, analyzer='word')
        5 lda_features = vectorizer.fit_transform(docs)
    ----> 6 lda_model = LatentDirichletAllocation(
        7     n_topics=10,
        8     learning_method='online',

    TypeError: __init__() got an unexpected keyword argument 'n_topics'
    ```

yields the following when rendered:

.. code-block:: python

    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-1-a674e682c281> in <module>
        4 vectorizer = CountVectorizer(input=docs, analyzer='word')
        5 lda_features = vectorizer.fit_transform(docs)
    ----> 6 lda_model = LatentDirichletAllocation(
        7     n_topics=10,
        8     learning_method='online',

    TypeError: __init__() got an unexpected keyword argument 'n_topics'

.. _synth_data:

Synthetic dataset
=================

Before choosing a particular synthetic dataset, first you have to identify the
type of problem you are solving: Is it a classification, a regression,
a clustering, etc?

Once that you narrowed down the type of problem, you need to provide a synthetic
dataset accordingly. Most of the times you only need a minimalistic dataset.
Here is a non-exhaustive list of tools that may help you.

NumPy
-----

NumPy tools such as `numpy.random.randn
<https://numpy.org/doc/stable/reference/random/generated/numpy.random.randn.html>`_
and `numpy.random.randint
<https://numpy.org/doc/stable/reference/random/generated/numpy.random.randint.html>`_
can be used to create dummy numeric data.

- regression

  Regressions take continuous numeric data as features and target.

  .. code-block:: python

      import numpy as np

      rng = np.random.RandomState(0)
      n_samples, n_features = 5, 5
      X = rng.randn(n_samples, n_features)
      y = rng.randn(n_samples)

A similar snippet can be used as synthetic data when testing scaling tools such
as :class:`sklearn.preprocessing.StandardScaler`.

- classification

  If the bug is not raised during when encoding a categorical variable, you can
  feed numeric data to a classifier. Just remember to ensure that the target
  is indeed an integer.

  .. code-block:: python

      import numpy as np

      rng = np.random.RandomState(0)
      n_samples, n_features = 5, 5
      X = rng.randn(n_samples, n_features)
      y = rng.randint(0, 2, n_samples)  # binary target with values in {0, 1}

  If the bug only happens with non-numeric class labels, you might want to
  generate a random target with `numpy.random.choice
  <https://numpy.org/doc/stable/reference/random/generated/numpy.random.choice.html>`_.

  .. code-block:: python

      import numpy as np

      rng = np.random.RandomState(0)
      n_samples, n_features = 50, 5
      X = rng.randn(n_samples, n_features)
      y = np.random.choice(
          ["male", "female", "other"], size=n_samples, p=[0.49, 0.49, 0.02]
      )

Pandas
------

Some scikit-learn objects expect pandas dataframes as input. In this case you can
transform numpy arrays into pandas objects using `pandas.DataFrame
<https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.html>`_, or
`pandas.Series
<https://pandas.pydata.org/docs/reference/api/pandas.Series.html>`_.

.. code-block:: python

    import numpy as np
    import pandas as pd

    rng = np.random.RandomState(0)
    n_samples, n_features = 5, 5
    X = pd.DataFrame(
        {
            "continuous_feature": rng.randn(n_samples),
            "positive_feature": rng.uniform(low=0.0, high=100.0, size=n_samples),
            "categorical_feature": rng.choice(["a", "b", "c"], size=n_samples),
        }
    )
    y = pd.Series(rng.randn(n_samples))

In addition, scikit-learn includes various :ref:`sample_generators` that can be
used to build artificial datasets of controlled size and complexity.

`make_regression`
-----------------

As hinted by the name, :class:`sklearn.datasets.make_regression` produces
regression targets with noise as an optionally-sparse random linear combination
of random features.

.. code-block:: python

    from sklearn.datasets import make_regression

    X, y = make_regression(n_samples=1000, n_features=20)

`make_classification`
---------------------

:class:`sklearn.datasets.make_classification` creates multiclass datasets with multiple Gaussian
clusters per class. Noise can be introduced by means of correlated, redundant or
uninformative features.

.. code-block:: python

    from sklearn.datasets import make_classification

    X, y = make_classification(
        n_features=2, n_redundant=0, n_informative=2, n_clusters_per_class=1
    )

`make_blobs`
------------

Similarly to `make_classification`, :class:`sklearn.datasets.make_blobs` creates
multiclass datasets using normally-distributed clusters of points. It provides
greater control regarding the centers and standard deviations of each cluster,
and therefore it is useful to demonstrate clustering.

.. code-block:: python

    from sklearn.datasets import make_blobs

    X, y = make_blobs(n_samples=10, centers=3, n_features=2)

Dataset loading utilities
-------------------------

You can use the :ref:`datasets` to load and fetch several popular reference
datasets. This option is useful when the bug relates to the particular structure
of the data, e.g. dealing with missing values or image recognition.

.. code-block:: python

    from sklearn.datasets import load_breast_cancer

    X, y = load_breast_cancer(return_X_y=True)

minimal reproducer                                                  Crafting a minimal reproducer for scikit learn                                                  Whether submitting a bug report  designing a suite of tests  or simply posting a question in the discussions  being able to craft minimal  reproducible examples  or minimal  workable examples  is the key to communicating effectively and efficiently with the community   There are very good guidelines on the internet such as  this StackOverflow document  https   stackoverflow com help mcve    or  this blogpost by Matthew Rocklin  https   matthewrocklin com blog work 2018 02 28 minimal bug reports    on crafting Minimal Complete Verifiable Examples  referred below as MCVE   Our goal is not to be repetitive with those references but rather to provide a step by step guide on how to narrow down a bug until you have reached the shortest possible code to reproduce it   The first step before submitting a bug report to scikit learn is to read the  Issue template  https   github com scikit learn scikit learn blob main  github ISSUE TEMPLATE bug report yml     It is already quite informative about the information you will be asked to provide        good practices   Good practices                 In this section we will focus on the   Steps Code to Reproduce   section of the  Issue template  https   github com scikit learn scikit learn blob main  github ISSUE TEMPLATE bug report yml     We will start with a snippet of code that already provides a failing example but that has room for readability improvement  We then craft a MCVE from it     Example       code block   python        I am currently working in a ML project and when I tried to fit a       GradientBoostingRegressor instance to my data csv I get a UserWarning         X has feature names  but DecisionTreeRegressor was fitted without       feature names   You can get a copy of my dataset from       https   example com my data csv and verify my features do have       names  The problem seems to arise during fit when I pass an integer       to the n iter no change parameter       df   pd read csv  my data csv       X   df   feature name      my features do have names     y   df  target          We set random state 42 for the train test split     X train  X test  y train  y test   train test split          X  y  test size 0 33  random state 42            scaler   StandardScaler with mean False      X train   scaler fit transform X train      X test   scaler transform X test         An instance with default n iter no change raises no error nor warnings     gbdt   GradientBoostingRegressor random state 0      gbdt fit X train  y train      default score   gbdt score X test  y test         the bug appears when I change the value for n iter no change     gbdt   GradientBoostingRegressor random state 0  n iter no change 5      gbdt fit X train  y train      other score   gbdt score X test  y test       other score   gbdt score X test  y test    Provide a failing code example with minimal comments                                                       Writing instructions to reproduce the problem in English is often ambiguous  Better make sure that all the necessary details to reproduce the problem are illustrated in the Python code snippet to avoid any ambiguity  Besides  by this point you already provided a concise description in the   Describe the bug   section of the  Issue template  https   github com scikit learn scikit learn blob main  github ISSUE TEMPLATE bug report yml      The following code  while   still not minimal    is already   much better   because it can be copy pasted in a Python terminal to reproduce the problem in one step  In particular     it contains   all necessary imports statements      it can fetch the public dataset without having to manually download a   file and put it in the expected location on the disk     Improved example       code block   python      import pandas as pd      df   pd read csv  https   example com my data csv       X   df   feature name        y   df  target        from sklearn model selection import train test split      X train  X test  y train  y test   train test split          X  y  test size 0 33  random state 42            from sklearn preprocessing import StandardScaler      scaler   StandardScaler with mean False      X train   scaler fit transform X train      X test   scaler transform X test       from sklearn ensemble import GradientBoostingRegressor      gbdt   GradientBoostingRegressor random state 0      gbdt fit X train  y train     no warning     default score   gbdt score X test  y test       gbdt   GradientBoostingRegressor random state 0  n iter no change 5      gbdt fit X train  y train     raises warning     other score   gbdt score X test  y test      other score   gbdt score X test  y test    Boil down your script to something as small as possible                                                          You have to ask yourself which lines of code are relevant and which are not for reproducing the bug  Deleting unnecessary lines of code or simplifying the function calls by omitting unrelated non default options will help you and other contributors narrow down the cause of the bug   In particular  for this specific example     the warning has nothing to do with the  train test split  since it already   appears in the training step  before we use the test set    similarly  the lines that compute the scores on the test set are not   necessary    the bug can be reproduced for any value of  random state  so leave it to its   default    the bug can be reproduced without preprocessing the data with the    StandardScaler      Improved example       code block   python      import pandas as pd     df   pd read csv  https   example com my data csv       X   df   feature name        y   df  target        from sklearn ensemble import GradientBoostingRegressor      gbdt   GradientBoostingRegressor       gbdt fit X  y     no warning      gbdt   GradientBoostingRegressor n iter no change 5      gbdt fit X  y     raises warning     DO NOT   report your data unless it is extremely necessary                                                               The idea is to make the code as self contained as possible  For doing so  you can use a  ref  synth data   It can be generated using numpy  pandas or the  mod  sklearn datasets  module  Most of the times the bug is not related to a particular structure of your data  Even if it is  try to find an available dataset that has similar characteristics to yours and that reproduces the problem  In this particular case  we are interested in data that has labeled feature names     Improved example       code block   python      import pandas as pd     from sklearn ensemble import GradientBoostingRegressor      df   pd DataFrame                         feature name     12 32  1 43  30 01  22 17                target    72  55  32  43                       X   df   feature name        y   df  target        gbdt   GradientBoostingRegressor       gbdt fit X  y    no warning     gbdt   GradientBoostingRegressor n iter no change 5      gbdt fit X  y    raises warning  As already mentioned  the key to communication is the readability of the code and good formatting can really be a plus  Notice that in the previous snippet we     try to limit all lines to a maximum of 79 characters to avoid horizontal   scrollbars in the code snippets blocks rendered on the GitHub issue    use blank lines to separate groups of related functions    place all the imports in their own group at the beginning   The simplification steps presented in this guide can be implemented in a different order than the progression we have shown here  The important points are     a minimal reproducer should be runnable by a simple copy and paste in a   python terminal    it should be simplified as much as possible by removing any code steps   that are not strictly needed to reproducing the original problem    it should ideally only rely on a minimal dataset generated on the fly by   running the code instead of relying on external data  if possible    Use markdown formatting                          To format code or text into its own distinct block  use triple backticks   Markdown  https   docs github com en get started writing on github getting started with writing and formatting on github basic writing and formatting syntax    supports an optional language identifier to enable syntax highlighting in your fenced code block  For example           python     from sklearn datasets import make blobs      n samples   100     n components   3     X  y   make blobs n samples n samples  centers n components           will render a python formatted snippet as follows     code block   python      from sklearn datasets import make blobs      n samples   100     n components   3     X  y   make blobs n samples n samples  centers n components   It is not necessary to create several blocks of code when submitting a bug report  Remember other reviewers are going to copy paste your code and having a single cell will make their task easier   In the section named   Actual results   of the  Issue template  https   github com scikit learn scikit learn blob main  github ISSUE TEMPLATE bug report yml    you are asked to provide the error message including the full traceback of the exception  In this case  use the  python traceback  qualifier  For example           python traceback                                                                                TypeError                                 Traceback  most recent call last       ipython input 1 a674e682c281  in  module          4 vectorizer   CountVectorizer input docs  analyzer  word           5 lda features   vectorizer fit transform docs            6 lda model   LatentDirichletAllocation          7     n topics 10          8     learning method  online        TypeError    init     got an unexpected keyword argument  n topics           yields the following when rendered      code block   python                                                                                TypeError                                 Traceback  most recent call last       ipython input 1 a674e682c281  in  module          4 vectorizer   CountVectorizer input docs  analyzer  word           5 lda features   vectorizer fit transform docs            6 lda model   LatentDirichletAllocation          7     n topics 10          8     learning method  online        TypeError    init     got an unexpected keyword argument  n topics        synth data   Synthetic dataset                    Before choosing a particular synthetic dataset  first you have to identify the type of problem you are solving  Is it a classification  a regression  a clustering  etc   Once that you narrowed down the type of problem  you need to provide a synthetic dataset accordingly  Most of the times you only need a minimalistic dataset  Here is a non exhaustive list of tools that may help you   NumPy        NumPy tools such as  numpy random randn  https   numpy org doc stable reference random generated numpy random randn html    and  numpy random randint  https   numpy org doc stable reference random generated numpy random randint html    can be used to create dummy numeric data     regression    Regressions take continuous numeric data as features and target        code block   python        import numpy as np        rng   np random RandomState 0        n samples  n features   5  5       X   rng randn n samples  n features        y   rng randn n samples   A similar snippet can be used as synthetic data when testing scaling tools such as  class  sklearn preprocessing StandardScaler      classification    If the bug is not raised during when encoding a categorical variable  you can   feed numeric data to a classifier  Just remember to ensure that the target   is indeed an integer        code block   python        import numpy as np        rng   np random RandomState 0        n samples  n features   5  5       X   rng randn n samples  n features        y   rng randint 0  2  n samples     binary target with values in  0  1      If the bug only happens with non numeric class labels  you might want to   generate a random target with  numpy random choice    https   numpy org doc stable reference random generated numpy random choice html           code block   python        import numpy as np        rng   np random RandomState 0        n samples  n features   50  5       X   rng randn n samples  n features        y   np random choice              male    female    other    size n samples  p  0 49  0 49  0 02           Pandas         Some scikit learn objects expect pandas dataframes as input  In this case you can transform numpy arrays into pandas objects using  pandas DataFrame  https   pandas pydata org docs reference api pandas DataFrame html     or  pandas Series  https   pandas pydata org docs reference api pandas Series html         code block   python      import numpy as np     import pandas as pd      rng   np random RandomState 0      n samples  n features   5  5     X   pd DataFrame                         continuous feature   rng randn n samples                positive feature   rng uniform low 0 0  high 100 0  size n samples                categorical feature   rng choice   a    b    c    size n samples                       y   pd Series rng randn n samples    In addition  scikit learn includes various  ref  sample generators  that can be used to build artificial datasets of controlled size and complexity    make regression                     As hinted by the name   class  sklearn datasets make regression  produces regression targets with noise as an optionally sparse random linear combination of random features      code block   python      from sklearn datasets import make regression      X  y   make regression n samples 1000  n features 20    make classification                          class  sklearn datasets make classification  creates multiclass datasets with multiple Gaussian clusters per class  Noise can be introduced by means of correlated  redundant or uninformative features      code block   python      from sklearn datasets import make classification      X  y   make classification          n features 2  n redundant 0  n informative 2  n clusters per class 1         make blobs                Similarly to  make classification    class  sklearn datasets make blobs  creates multiclass datasets using normally distributed clusters of points  It provides greater control regarding the centers and standard deviations of each cluster  and therefore it is useful to demonstrate clustering      code block   python      from sklearn datasets import make blobs      X  y   make blobs n samples 10  centers 3  n features 2   Dataset loading utilities                            You can use the  ref  datasets  to load and fetch several popular reference datasets  This option is useful when the bug relates to the particular structure of the data  e g  dealing with missing values or image recognition      code block   python      from sklearn datasets import load breast cancer      X  y   load breast cancer return X y True


terraform page title AWS Cost Estimation HCP Terraform Supported AWS resources in HCP Terraform Cost Estimation Learn which AWS resources HCP Terraform includes in cost estimation HCP Terraform can estimate monthly costs for many AWS Terraform resources

Answer:
---
page_title: AWS - Cost Estimation - HCP Terraform
description: >-
  Learn which AWS resources HCP Terraform includes in cost estimation.
---

# Supported AWS resources in HCP Terraform Cost Estimation

HCP Terraform can estimate monthly costs for many AWS Terraform resources.

-> **Note:** Terraform Enterprise requires AWS credentials to support cost estimation. These credentials are configured at the instance level, not the organization level. See the [Application Administration docs](/terraform/enterprise/admin/application/integration) for more details.

## Supported Resources

Cost estimation supports the following resources. Not all possible values for attributes of each resource are supported, ex. newer instance types or EBS volume types.

| Resource | Incurs Cost |
| ----------- | ----------- |
| `aws_alb` | X |
| `aws_autoscaling_group` | X |
| `aws_cloudhsm_v2_hsm` | X |
| `aws_cloudwatch_dashboard` | X |
| `aws_cloudwatch_metric_alarm` | X |
| `aws_db_instance` | X |
| `aws_dynamodb_table` | X |
| `aws_ebs_volume` | X |
| `aws_elasticache_cluster` | X |
| `aws_elasticsearch_domain` | X |
| `aws_elb` | X |
| `aws_instance` | X |
| `aws_kms_key` | X |
| `aws_lb` | X |
| `aws_rds_cluster_instance` | X |
| `aws_acm_certificate_validation` | |
| `aws_alb_listener` | |
| `aws_alb_listener_rule` | |
| `aws_alb_target_group` | |
| `aws_alb_target_group_attachment` | |
| `aws_api_gateway_api_key` | |
| `aws_api_gateway_deployment` | |
| `aws_api_gateway_integration` | |
| `aws_api_gateway_integration_response` | |
| `aws_api_gateway_method` | |
| `aws_api_gateway_method_response` | |
| `aws_api_gateway_resource` | |
| `aws_api_gateway_usage_plan_key` | |
| `aws_appautoscaling_policy` | |
| `aws_appautoscaling_target` | |
| `aws_autoscaling_lifecycle_hook` | |
| `aws_autoscaling_policy` | |
| `aws_cloudformation_stack` | |
| `aws_cloudfront_distribution` | |
| `aws_cloudfront_origin_access_identity` | |
| `aws_cloudwatch_event_rule` | |
| `aws_cloudwatch_event_target` | |
| `aws_cloudwatch_log_group` | |
| `aws_cloudwatch_log_metric_filter` | |
| `aws_cloudwatch_log_stream` | |
| `aws_cloudwatch_log_subscription_filter` | |
| `aws_codebuild_webhook` | |
| `aws_codedeploy_deployment_group` | |
| `aws_cognito_identity_provider` | |
| `aws_cognito_user_pool` | |
| `aws_cognito_user_pool_client` | |
| `aws_cognito_user_pool_domain` | |
| `aws_config_config_rule` | |
| `aws_customer_gateway` | |
| `aws_db_parameter_group` | |
| `aws_db_subnet_group` | |
| `aws_dynamodb_table_item` | |
| `aws_ecr_lifecycle_policy` | |
| `aws_ecr_repository_policy` | |
| `aws_ecs_cluster` | |
| `aws_ecs_task_definition` | |
| `aws_efs_mount_target` | |
| `aws_eip_association` | |
| `aws_elastic_beanstalk_application` | |
| `aws_elastic_beanstalk_application_version` | |
| `aws_elastic_beanstalk_environment` | |
| `aws_elasticache_parameter_group` | |
| `aws_elasticache_subnet_group` | |
| `aws_flow_log` | |
| `aws_iam_access_key` | |
| `aws_iam_account_alias` | |
| `aws_iam_account_password_policy` | |
| `aws_iam_group` | |
| `aws_iam_group_membership` | |
| `aws_iam_group_policy` | |
| `aws_iam_group_policy_attachment` | |
| `aws_iam_instance_profile` | |
| `aws_iam_policy` | |
| `aws_iam_policy_attachment` | |
| `aws_iam_role` | |
| `aws_iam_role_policy` | |
| `aws_iam_role_policy_attachment` | |
| `aws_iam_saml_provider` | |
| `aws_iam_service_linked_role` | |
| `aws_iam_user` | |
| `aws_iam_user_group_membership` | |
| `aws_iam_user_login_profile` | |
| `aws_iam_user_policy` | |
| `aws_iam_user_policy_attachment` | |
| `aws_iam_user_ssh_key` | |
| `aws_internet_gateway` | |
| `aws_key_pair` | |
| `aws_kms_alias` | |
| `aws_lambda_alias` | |
| `aws_lambda_event_source_mapping` | |
| `aws_lambda_function` | |
| `aws_lambda_layer_version` | |
| `aws_lambda_permission` | |
| `aws_launch_configuration` | |
| `aws_lb_listener` | |
| `aws_lb_listener_rule` | |
| `aws_lb_target_group` | |
| `aws_lb_target_group_attachment` | |
| `aws_network_acl` | |
| `aws_network_acl_rule` | |
| `aws_network_interface` | |
| `aws_placement_group` | |
| `aws_rds_cluster_parameter_group` | |
| `aws_route` | |
| `aws_route53_record` | |
| `aws_route53_zone_association` | |
| `aws_route_table` | |
| `aws_route_table_association` | |
| `aws_s3_bucket` | |
| `aws_s3_bucket_notification` | |
| `aws_s3_bucket_object` | |
| `aws_s3_bucket_policy` | |
| `aws_s3_bucket_public_access_block` | |
| `aws_security_group` | |
| `aws_security_group_rule` | |
| `aws_service_discovery_service` | |
| `aws_sfn_state_machine` | |
| `aws_sns_topic` | |
| `aws_sns_topic_subscription` | |
| `aws_sqs_queue` | |
| `aws_sqs_queue_policy` | |
| `aws_ssm_maintenance_window` | |
| `aws_ssm_maintenance_window_target` | |
| `aws_ssm_maintenance_window_task` | |
| `aws_ssm_parameter` | |
| `aws_subnet` | |
| `aws_volume_attachment` | |
| `aws_vpc` | |
| `aws_vpc_dhcp_options` | |
| `aws_vpc_dhcp_options_association` | |
| `aws_vpc_endpoint` | |
| `aws_vpc_endpoint_route_table_association` | |
| `aws_vpc_endpoint_service` | |
| `aws_vpc_ipv4_cidr_block_association` | |
| `aws_vpc_peering_connection_accepter` | |
| `aws_vpc_peering_connection_options` | |
| `aws_vpn_connection_route` | |
| `aws_waf_ipset` | |
| `aws_waf_rule` | |
| `aws_waf_web_acl` | |

page title  AWS   Cost Estimation   HCP Terraform description       Learn which AWS resources HCP Terraform includes in cost estimation         Supported AWS resources in HCP Terraform Cost Estimation  HCP Terraform can estimate monthly costs for many AWS Terraform resources        Note    Terraform Enterprise requires AWS credentials to support cost estimation  These credentials are configured at the instance level  not the organization level  See the  Application Administration docs   terraform enterprise admin application integration  for more details      Supported Resources  Cost estimation supports the following resources  Not all possible values for attributes of each resource are supported  ex  newer instance types or EBS volume types     Resource   Incurs Cost                                    aws alb    X      aws autoscaling group    X      aws cloudhsm v2 hsm    X      aws cloudwatch dashboard    X      aws cloudwatch metric alarm    X      aws db instance    X      aws dynamodb table    X      aws ebs volume    X      aws elasticache cluster    X      aws elasticsearch domain    X      aws elb    X      aws instance    X      aws kms key    X      aws lb    X      aws rds cluster instance    X      aws acm certificate validation         aws alb listener         aws alb listener rule         aws alb target group         aws alb target group attachment         aws api gateway api key         aws api gateway deployment         aws api gateway integration         aws api gateway integration response         aws api gateway method         aws api gateway method response         aws api gateway resource         aws api gateway usage plan key         aws appautoscaling policy         aws appautoscaling target         aws autoscaling lifecycle hook         aws autoscaling policy         aws cloudformation stack         aws cloudfront distribution         aws cloudfront origin access identity         aws cloudwatch event rule         aws cloudwatch event target         aws cloudwatch log group         aws cloudwatch log metric filter         aws cloudwatch log stream         aws cloudwatch log subscription filter         aws codebuild webhook         aws codedeploy deployment group         aws cognito identity provider         aws cognito user pool         aws cognito user pool client         aws cognito user pool domain         aws config config rule         aws customer gateway         aws db parameter group         aws db subnet group         aws dynamodb table item         aws ecr lifecycle policy         aws ecr repository policy         aws ecs cluster         aws ecs task definition         aws efs mount target         aws eip association         aws elastic beanstalk application         aws elastic beanstalk application version         aws elastic beanstalk environment         aws elasticache parameter group         aws elasticache subnet group         aws flow log         aws iam access key         aws iam account alias         aws iam account password policy         aws iam group         aws iam group membership         aws iam group policy         aws iam group policy attachment         aws iam instance profile         aws iam policy         aws iam policy attachment         aws iam role         aws iam role policy         aws iam role policy attachment         aws iam saml provider         aws iam service linked role         aws iam user         aws iam user group membership         aws iam user login profile         aws iam user policy         aws iam user policy attachment         aws iam user ssh key         aws internet gateway         aws key pair         aws kms alias         aws lambda alias         aws lambda event source mapping         aws lambda function         aws lambda layer version         aws lambda permission         aws launch configuration         aws lb listener         aws lb listener rule         aws lb target group         aws lb target group attachment         aws network acl         aws network acl rule         aws network interface         aws placement group         aws rds cluster parameter group         aws route         aws route53 record         aws route53 zone association         aws route table         aws route table association         aws s3 bucket         aws s3 bucket notification         aws s3 bucket object         aws s3 bucket policy         aws s3 bucket public access block         aws security group         aws security group rule         aws service discovery service         aws sfn state machine         aws sns topic         aws sns topic subscription         aws sqs queue         aws sqs queue policy         aws ssm maintenance window         aws ssm maintenance window target         aws ssm maintenance window task         aws ssm parameter         aws subnet         aws volume attachment         aws vpc         aws vpc dhcp options         aws vpc dhcp options association         aws vpc endpoint         aws vpc endpoint route table association         aws vpc endpoint service         aws vpc ipv4 cidr block association         aws vpc peering connection accepter         aws vpc peering connection options         aws vpn connection route         aws waf ipset         aws waf rule         aws waf web acl


terraform page title Review deployment plans Review deployment plans Deployment plans are a combination of an individual configuration version and one of your stack s deployments As in the traditional Terraform workflow HCP Terraform creates plans every time a new configuration version introduces potential changes for a deployment Learn how to review deployment plans in HCP Terraform Stacks tfc only true

Answer:
---
page_title: Review deployment plans
description: Learn how to review deployment plans in HCP Terraform Stacks.
tfc_only: true
---

# Review deployment plans

Deployment plans are a combination of an individual configuration version and one of your stack’s deployments. As in the traditional Terraform workflow, HCP Terraform creates plans every time a new configuration version introduces potential changes for a deployment.

This guide explains how to review and approve deployment plans in HCP Terraform.

## Requirements

To view a Stack and its plans, you must also be a member of a team in your organization with one of the following permissions:
* [Organization-level **View all projects**](/terraform/cloud-docs/users-teams-organizations/permissions#view-all-projects) or higher
* [Project-level **Write**](/terraform/cloud-docs/users-teams-organizations/permissions#write) or higher

## View a deployment

If you are not already on your stack’s deployment page, navigate to it:

1. In the navigation menu, click **Projects** under **Manage**.
1. Select the project containing your Stack.
1. Click **Stacks** in the navigation menu.
1. Select the Stack you want to review.

A stack’s **Overview** page displays the following information:

* The number of your stack’s components and deployments
* Your deployment’s current [health](#check-deployment-health)
* The latest configuration version
* A chart listing each deployment’s recent configuration versions

To view all of the plans for a deployment, click the name of the deployment you want to review.

A deployment’s page lists its components and the last five deployment plans. Clicking on a component reveals all of the resources it contains. Opening the **Inspect** dropdown menu on a deployment's page reveals the option to download:

* **State description** downloads that deployment’s current state.
* **Provider schemas** downloads the schema of the providers of your deployment.

### View plans

A Stack deployment can have multiple plans. In a deployment's page, underneath **Latest plans**, each deployment plan lists:

* The plan name
* The trigger why HCP Terraform created this plan
* The configuration version HCP Terraform created the plan with
* When HCP Terraform created the plan

You can see a plan’s full details by clicking the plan’s name or an abbreviated list of the plan’s changes by clicking **Quick View**. You can also click **View all plans** to display a list of all the plans for this deployment. You can filter plans by [health status](#check-deployment-health) in the list of all plans.

Each plan includes a timeline detailing when the plan started, when it received its configuration version, and when it was approved.

### Check deployment health

Click **Overview** in the sidebar of your Stack to view the status of each of your deployments.

| Status | Description |
| :---- | :---- |
| Healthy | HCP Terraform is not applying this deployment, no plans await approval, and no diagnostic alerts exist. |
| Deploying | A plan is approved, and HCP Terraform is applying it. |
| Plans waiting for approval | HCP Terraform created a plan successfully and is waiting for approval. |
| Error diagnostics | The deployment has error diagnostic alerts. |
| Warning diagnostics | The deployment has warning diagnostic alerts. |

## Download plan data

You can download Stack plan data to debug and analyze how your Stack changes over time.

Select one of the following options in the **Inspect** drop-down to perform the associated action:

* **View plan orchestration results** displays HCP Terraform's decisions while making this plan.
* **Download plan event stream** downloads a log file of your plan’s events.
* **Download plan description** downloads a file with all plan information.
* **View apply orchestration results** displays HCP Terraform's decisions to apply this plan.
* **Download apply event stream** downloads a log file of your plan’s events.
* **Download apply description** downloads a file with all the information about this applied plan.

## Approve plans

Like traditional Terraform plans, Stack deployment plans list the changes that will occur if you approve that plan. Each component lists its expected resource changes, and you can review those changes as you decide whether to apply a plan.

When viewing a deployment plan, HCP Terraform notes if that plan is awaiting approval. Click **Approve plan** if you want HCP Terraform to apply a plan to this deployment or **Discard plan** to ignore it. You manage each deployment independently, so any plans you approve only affect the current deployment you are interacting with.

### Convergence checks

After applying any plan, HCP Terraform automatically triggers a plan called a convergence check. A convergence check is a re-plan to ensure components do not have any [deferred changes](#deferred-changes). HCP Terraform continues to trigger new plans until the convergence check returns a plan that does not contain changes.

By default, each Stack has an `auto-approve` rule named `empty_plan`, which auto-approves a plan if it does not contain changes. When a convergence check contains no changes, HCP Terraform auto-applies that plan.

## Deferred changes

Like with Terraform configuration files, HCP Terraform generates a dependency graph and creates resources defined in `*.tfstack.hcl` and `*.tfdeploy.hcl` files.

When you deploy a Stack with resources that depend on resources provisioned by other components in your stack, HCP Terraform recognizes the dependency between components and automatically defers that plan until HCP Terraform can complete it successfully. Plans with deferred changes are plans with resources that depend on resources that don't exist yet, requiring follow-up plans.

-> **Hands-on**: Complete the [Manage Kubernetes workloads with stacks](/terraform/tutorials/cloud/stacks-eks-deferred) tutorial to create plans with deferred changes.

HCP Terraform notifies you in the UI if a plan contains deferred changes. Approving a plan with deferred changes makes HCP Terraform automatically create a follow-up plan to properly set up resources in the order of operations those resources require.

After applying a plan with deferred changes, HCP Terraform notifies you of any replans it creates with a link to **View replan**. You can review the replan to ensure HCP Terraform created your resources as expected

page title  Review deployment plans description  Learn how to review deployment plans in HCP Terraform Stacks  tfc only  true        Review deployment plans  Deployment plans are a combination of an individual configuration version and one of your stack s deployments  As in the traditional Terraform workflow  HCP Terraform creates plans every time a new configuration version introduces potential changes for a deployment    This guide explains how to review and approve deployment plans in HCP Terraform      Requirements  To view a Stack and its plans  you must also be a member of a team in your organization with one of the following permissions     Organization level   View all projects     terraform cloud docs users teams organizations permissions view all projects  or higher    Project level   Write     terraform cloud docs users teams organizations permissions write  or higher     View a deployment  If you are not already on your stack s deployment page  navigate to it   1  In the navigation menu  click   Projects   under   Manage      1  Select the project containing your Stack    1  Click   Stacks   in the navigation menu    1  Select the Stack you want to review   A stack s   Overview   page displays the following information     The number of your stack s components and deployments     Your deployment s current  health   check deployment health      The latest configuration version     A chart listing each deployment s recent configuration versions  To view all of the plans for a deployment  click the name of the deployment you want to review   A deployment s page lists its components and the last five deployment plans  Clicking on a component reveals all of the resources it contains  Opening the   Inspect   dropdown menu on a deployment s page reveals the option to download        State description   downloads that deployment s current state        Provider schemas   downloads the schema of the providers of your deployment        View plans  A Stack deployment can have multiple plans  In a deployment s page  underneath   Latest plans    each deployment plan lists     The plan name      The trigger why HCP Terraform created this plan     The configuration version HCP Terraform created the plan with     When HCP Terraform created the plan  You can see a plan s full details by clicking the plan s name or an abbreviated list of the plan s changes by clicking   Quick View    You can also click   View all plans   to display a list of all the plans for this deployment  You can filter plans by  health status   check deployment health  in the list of all plans    Each plan includes a timeline detailing when the plan started  when it received its configuration version  and when it was approved         Check deployment health  Click   Overview   in the sidebar of your Stack to view the status of each of your deployments      Status   Description                       Healthy   HCP Terraform is not applying this deployment  no plans await approval  and no diagnostic alerts exist      Deploying   A plan is approved  and HCP Terraform is applying it      Plans waiting for approval   HCP Terraform created a plan successfully and is waiting for approval      Error diagnostics   The deployment has error diagnostic alerts      Warning diagnostics   The deployment has warning diagnostic alerts         Download plan data  You can download Stack plan data to debug and analyze how your Stack changes over time    Select one of the following options in the   Inspect   drop down to perform the associated action       View plan orchestration results   displays HCP Terraform s decisions while making this plan        Download plan event stream   downloads a log file of your plan s events         Download plan description   downloads a file with all plan information        View apply orchestration results   displays HCP Terraform s decisions to apply this plan        Download apply event stream   downloads a log file of your plan s events        Download apply description   downloads a file with all the information about this applied plan      Approve plans  Like traditional Terraform plans  Stack deployment plans list the changes that will occur if you approve that plan  Each component lists its expected resource changes  and you can review those changes as you decide whether to apply a plan    When viewing a deployment plan  HCP Terraform notes if that plan is awaiting approval  Click   Approve plan   if you want HCP Terraform to apply a plan to this deployment or   Discard plan   to ignore it  You manage each deployment independently  so any plans you approve only affect the current deployment you are interacting with       Convergence checks  After applying any plan  HCP Terraform automatically triggers a plan called a convergence check  A convergence check is a re plan to ensure components do not have any  deferred changes   deferred changes   HCP Terraform continues to trigger new plans until the convergence check returns a plan that does not contain changes    By default  each Stack has an  auto approve  rule named  empty plan   which auto approves a plan if it does not contain changes  When a convergence check contains no changes  HCP Terraform auto applies that plan      Deferred changes  Like with Terraform configuration files  HCP Terraform generates a dependency graph and creates resources defined in    tfstack hcl  and    tfdeploy hcl  files    When you deploy a Stack with resources that depend on resources provisioned by other components in your stack  HCP Terraform recognizes the dependency between components and automatically defers that plan until HCP Terraform can complete it successfully  Plans with deferred changes are plans with resources that depend on resources that don t exist yet  requiring follow up plans        Hands on    Complete the  Manage Kubernetes workloads with stacks   terraform tutorials cloud stacks eks deferred  tutorial to create plans with deferred changes   HCP Terraform notifies you in the UI if a plan contains deferred changes  Approving a plan with deferred changes makes HCP Terraform automatically create a follow up plan to properly set up resources in the order of operations those resources require    After applying a plan with deferred changes  HCP Terraform notifies you of any replans it creates with a link to   View replan    You can review the replan to ensure HCP Terraform created your resources as expected


terraform Manage projects page title Manage projects in HCP Terraform and Terraform Enterprise This topic describes how to create and manage projects in HCP Terraform and Terraform Enterprise A project is a folder containing one or more workspaces Use projects to organize and group workspaces and create ownership boundaries across your infrastructure

Answer:
---
page_title: Manage projects in HCP Terraform and Terraform Enterprise
description: |-
  Use projects to organize and group workspaces and create ownership boundaries
  across your infrastructure.
---

# Manage projects

This topic describes how to create and manage projects in HCP Terraform and Terraform Enterprise. A project is a folder containing one or more workspaces.

## Requirements

You must have the following permissions to manage projects:

- You must be a member of a team with the **Manage all Projects**  permissions enabled to create a project. Refer to [Organization Permissions](/terraform/cloud-docs/users-teams-organizations/permissions#organization-permissions) for additional information.
- You must be a member of a team with the **Visible** option enabled under **Visibility** in the organization settings to configure a new team's access to the project. Refer to [Team Visibility](/terraform/cloud-docs/users-teams-organizations/teams/manage#team-visibility) for additional information.
- You must be a member of a team with update and delete permissions to be able to update and delete teams respectively.

To delete tags on a project, you must be member of a team with the **Admin** permission group enabled for the project.

To create tags for a project, you must be member of a team with the **Write** permission group enabled for the project.

## View a project

To view your organization's projects:

1. Click **Projects**.
1. Search for a project that you want to view. You can use the following methods:
   - Sort by column header.
   - Use the search bar to search on the name of a project or a tag.
1. Click on a project's name to view more details.

## Create a project

1. Click **Projects**.
1. Click **+ New project**.
1. Specify a name for the project. The name must be unique within the organization and can only include letters, numbers, inner spaces, hyphens, and underscores.
1. Add a description for the project. This field is optional.

    ~> **Adding project tags is in private beta and unavailable for some users.** Skip to step 8 if your interface does not include elements for adding tags. Contact your HashiCorp representative for information about participating in the private beta.

1. Open the **Add key value tags** menu to add tags to your project. Tags are optional key-value pairs that you can use to organize projects. Any workspaces you create within the project inherit project tags. Refer to [Define project tags](#define-project-tags) for additional information.
1. Click **+Add tag** and specify a tag key and tag value. If your organization has defined reserved tag keys, they appear in the **Tag key** field as suggestions. Refer to [Create and manage reserved tags](/terraform/cloud-docs/users-teams-organizations/organizations#create-and-manage-reserved-tags) for additional information.
1. Click **+add another tag** to attach any additional tags.
1. Click **Create** to finish creating the project.

HCP Terraform returns a new project page displaying all the project
information.

## Edit a project

1. Click **Projects**.
1. Click on a project name of the project you want to edit.
1. Click **Settings**.

On this **General settings** page, you can update the project name, project
description, and delete the project. On the **Team access** page, you can modify
team access to the project.

## Automatically destroy inactive workspaces

<!-- BEGIN: TFC:only name:pnp-callout -->
@include 'tfc-package-callouts/ephemeral-workspaces.mdx'
<!-- END: TFC:only name:pnp-callout -->

You can configure HCP Terraform to automatically destroy each workspace's
infrastructure in a project after a period of inactivity. A workspace
is _inactive_ if the workspace's state has not changed within your designated
time period.

If you configure a project to auto-destroy its infrastructure when inactive,
any run that updates Terraform state further delays the scheduled auto-destroy
time by the length of your designated timeframe.

!> **Warning:** Automatic destroy plans _do not_ prompt you for apply approval in the HCP Terraform user interface. We recommend only using this setting for development environments.

To schedule an auto-destroy run after a period of workspace inactivity:

1. Navigate to the project's **Settings** > **Auto-destroy Workspaces** page.
1. Click **Set up default**.
1. Select or customize a desired timeframe of inactivity.
1. Click **Confirm default**.

You can configure an individual workspace's auto-destroy settings to override
this default configuration. Refer to [automatically destroy workspaces](/terraform/cloud-docs/workspaces/settings/deletion#automatically-destroy) for more information.

## Delete a project

You can only delete projects that do not contain workspaces.

To delete an empty project:

1. Click **Projects**.
1. Search for a project that you want to review by scrolling down the table or
   searching for a project name in the search bar above the project table.
1. Click **Settings**. The settings view for the selected project appears.
1. Click the **Delete** button. A **Delete project** modal appears.
1. Click the **Delete** button to confirm the deletion.

HCP Terraform returns to the **Projects** view with the deleted project
removed from the list.

## Define project tags

~> **Adding project tags is in private beta and unavailable for some users.** Contact your HashiCorp representative for information about participating in the private beta.

You can define tags stored as key-value pairs to help you organize your projects and track resource consumption. HCP Terraform applies tags that you attach to projects to the workspaces created inside the project.

Workspace administrators with appropriate permissions can attach new key-value pairs to their workspaces to override inherited tags. Refer to [Create workspace tags](/terraform/cloud-docs/workspaces/tags) for additional information about using tags in workspaces.

Tags that you create appear in the tags management screen in the organization settings. Refer to [Organizations](/terraform/cloud-docs/users-teams-organizations/organizations) for additional information.

The following rules apply to tag keys and values:

- Tags must be one or more characters.
- Tags have a 255 character limit.
- Tags can include letters, numbers, colons, hyphens, and underscores.
- Tag values are optional.
- You can create up to 10 unique tags per workspace and 10 unique tags per project. As a result, each workspace can have up to 20 tags.
- You cannot use the following strings at the beginning of a tag key:
    - `hcp`
    - `hc`
    - `ibm

page title  Manage projects in HCP Terraform and Terraform Enterprise description       Use projects to organize and group workspaces and create ownership boundaries   across your infrastructure         Manage projects  This topic describes how to create and manage projects in HCP Terraform and Terraform Enterprise  A project is a folder containing one or more workspaces      Requirements  You must have the following permissions to manage projects     You must be a member of a team with the   Manage all Projects    permissions enabled to create a project  Refer to  Organization Permissions   terraform cloud docs users teams organizations permissions organization permissions  for additional information    You must be a member of a team with the   Visible   option enabled under   Visibility   in the organization settings to configure a new team s access to the project  Refer to  Team Visibility   terraform cloud docs users teams organizations teams manage team visibility  for additional information    You must be a member of a team with update and delete permissions to be able to update and delete teams respectively   To delete tags on a project  you must be member of a team with the   Admin   permission group enabled for the project   To create tags for a project  you must be member of a team with the   Write   permission group enabled for the project      View a project  To view your organization s projects   1  Click   Projects    1  Search for a project that you want to view  You can use the following methods       Sort by column header       Use the search bar to search on the name of a project or a tag  1  Click on a project s name to view more details       Create a project  1  Click   Projects    1  Click     New project    1  Specify a name for the project  The name must be unique within the organization and can only include letters  numbers  inner spaces  hyphens  and underscores  1  Add a description for the project  This field is optional               Adding project tags is in private beta and unavailable for some users    Skip to step 8 if your interface does not include elements for adding tags  Contact your HashiCorp representative for information about participating in the private beta     1  Open the   Add key value tags   menu to add tags to your project  Tags are optional key value pairs that you can use to organize projects  Any workspaces you create within the project inherit project tags  Refer to  Define project tags   define project tags  for additional information  1  Click    Add tag   and specify a tag key and tag value  If your organization has defined reserved tag keys  they appear in the   Tag key   field as suggestions  Refer to  Create and manage reserved tags   terraform cloud docs users teams organizations organizations create and manage reserved tags  for additional information  1  Click    add another tag   to attach any additional tags  1  Click   Create   to finish creating the project   HCP Terraform returns a new project page displaying all the project information      Edit a project  1  Click   Projects    1  Click on a project name of the project you want to edit  1  Click   Settings     On this   General settings   page  you can update the project name  project description  and delete the project  On the   Team access   page  you can modify team access to the project      Automatically destroy inactive workspaces        BEGIN  TFC only name pnp callout      include  tfc package callouts ephemeral workspaces mdx       END  TFC only name pnp callout      You can configure HCP Terraform to automatically destroy each workspace s infrastructure in a project after a period of inactivity  A workspace is  inactive  if the workspace s state has not changed within your designated time period   If you configure a project to auto destroy its infrastructure when inactive   any run that updates Terraform state further delays the scheduled auto destroy  time by the length of your designated timeframe        Warning    Automatic destroy plans  do not  prompt you for apply approval in the HCP Terraform user interface  We recommend only using this setting for development environments   To schedule an auto destroy run after a period of workspace inactivity   1  Navigate to the project s   Settings       Auto destroy Workspaces   page  1  Click   Set up default    1  Select or customize a desired timeframe of inactivity  1  Click   Confirm default     You can configure an individual workspace s auto destroy settings to override this default configuration  Refer to  automatically destroy workspaces   terraform cloud docs workspaces settings deletion automatically destroy  for more information      Delete a project  You can only delete projects that do not contain workspaces   To delete an empty project   1  Click   Projects    1  Search for a project that you want to review by scrolling down the table or    searching for a project name in the search bar above the project table  1  Click   Settings    The settings view for the selected project appears  1  Click the   Delete   button  A   Delete project   modal appears  1  Click the   Delete   button to confirm the deletion   HCP Terraform returns to the   Projects   view with the deleted project removed from the list      Define project tags       Adding project tags is in private beta and unavailable for some users    Contact your HashiCorp representative for information about participating in the private beta     You can define tags stored as key value pairs to help you organize your projects and track resource consumption  HCP Terraform applies tags that you attach to projects to the workspaces created inside the project   Workspace administrators with appropriate permissions can attach new key value pairs to their workspaces to override inherited tags  Refer to  Create workspace tags   terraform cloud docs workspaces tags  for additional information about using tags in workspaces   Tags that you create appear in the tags management screen in the organization settings  Refer to  Organizations   terraform cloud docs users teams organizations organizations  for additional information   The following rules apply to tag keys and values     Tags must be one or more characters    Tags have a 255 character limit    Tags can include letters  numbers  colons  hyphens  and underscores    Tag values are optional    You can create up to 10 unique tags per workspace and 10 unique tags per project  As a result  each workspace can have up to 20 tags    You cannot use the following strings at the beginning of a tag key         hcp         hc         ibm