...

Source file src/github.com/emissary-ingress/emissary/v3/pkg/api/getambassador.io/v2/doc.go

Documentation: github.com/emissary-ingress/emissary/v3/pkg/api/getambassador.io/v2

     1  // -*- fill-column: 70 -*-
     2  
     3  // Copyright 2020-2021 Datawire.  All rights reserved
     4  //
     5  // Licensed under the Apache License, Version 2.0 (the "License"); you
     6  // may not use this file except in compliance with the License.  You
     7  // may obtain a copy of the License at
     8  //
     9  //     http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing, software
    12  // distributed under the License is distributed on an "AS IS" BASIS,
    13  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
    14  // implied.  See the License for the specific language governing
    15  // permissions and limitations under the License.
    16  
    17  //////////////////////////////////////////////////////////////////////
    18  // 0. Table of Contents //////////////////////////////////////////////
    19  //////////////////////////////////////////////////////////////////////
    20  //
    21  // This file deals with common package/apiVersion-level things not
    22  // specific to any individual CRD:
    23  //
    24  //  1. Magic markers: Document the various magic "+marker" comments
    25  //     that are used in this package, and set up the package-level
    26  //     markers.
    27  //
    28  //  2. Package documentation: The `godoc` package-wide documentation.
    29  //
    30  //  3. Scheme: Set up the Group/Version/SchemeBuilder/AddToScheme for
    31  //     this apiVersion.
    32  //
    33  //  4. API design guidelines: Guidelines for additions to this
    34  //     package.
    35  //
    36  // Things that are shared between multiple CRDs, but are for
    37  // individual CRDs rather than the package/apiVersion as a whole, do
    38  // not belong in this file; they belong in `common.go`.
    39  
    40  //////////////////////////////////////////////////////////////////////
    41  // 1. Magic markers //////////////////////////////////////////////////
    42  //////////////////////////////////////////////////////////////////////
    43  //
    44  // We use a bunch of magic comments called "+markers" that serve as
    45  // input to `controller-gen` and `conversion-gen`.  Note that while
    46  // `controller-gen` doesn't care about what file these are in, the
    47  // older `k8s.io/gengo`-based `conversion-gen` specifically looks for
    48  // `doc.go`.  Mostly they annotate a type, or a field within a struct.
    49  // Just below here, we do the "global" package-level markers; these
    50  // package-level markers need to come before the "package" line.
    51  //
    52  // The type markers of interest are:
    53  //
    54  //  - "+kubebuilder:object:generate=bool" whether to generate
    55  //    `DeepCopy` and `DeepCopyInto` methods for this type; but we
    56  //    don't actually set this on types, since we can set it to true
    57  //    for all types at the package-level.
    58  //
    59  //  - "+kubebuilder:object:root=bool" whether to *also* generate a
    60  //    `DeepCopyObject` method.  It upsets me that controller-gen
    61  //    doesn't infer this based on the presence of metav1.TypeMeta
    62  //    inside of the type.
    63  //
    64  //  - "+kubebuilder:subresource:status" whether to add "status" as a
    65  //    subresource for that type.  It upsets me that controller-gen
    66  //    doesn't infer this based on the presence of a `status` field
    67  //    inside of the type.
    68  //
    69  // The field markers of interest are:
    70  //
    71  //  - The "+kubebuilder:validation:*" markers control the OpenAPI v3
    72  //    validation schema that is generated for this field.  ":Optional"
    73  //    or ":Required" may be applied at the package-level in order to
    74  //    set the default for all fields.  Most of the others can also be
    75  //    set at the type level.
    76  //
    77  // Package-level markers:
    78  //
    79  // The group name to use for the CRDs in the generated YAML:
    80  // +groupName=getambassador.io
    81  // +versionName=v2
    82  //
    83  // By default, mark all types in this package to have DeepCopy methods
    84  // generated (so we don't need to specify this for every type):
    85  // +kubebuilder:object:generate=true
    86  //
    87  // By default, mark all fields as optional (so we don't need to
    88  // specify this for every optional field, since most fields are
    89  // optional; and also because controller-gen's "required-by-default"
    90  // mode is broken and always makes everything optional, even if it's
    91  // explicitly marked as required):
    92  // +kubebuilder:validation:Optional
    93  //
    94  // Have conversion-gen help write the code to convert to and from
    95  // newer CRD versions.
    96  // +k8s:conversion-gen=github.com/emissary-ingress/emissary/v3/pkg/api/getambassador.io/v3alpha1
    97  
    98  //////////////////////////////////////////////////////////////////////
    99  // 2. Package documentation //////////////////////////////////////////
   100  //////////////////////////////////////////////////////////////////////
   101  
   102  // Package v2 contains API Schema definitions for the getambassador.io
   103  // v2 API group
   104  package v2
   105  
   106  //////////////////////////////////////////////////////////////////////
   107  // 3. Scheme /////////////////////////////////////////////////////////
   108  //////////////////////////////////////////////////////////////////////
   109  
   110  import (
   111  	"k8s.io/apimachinery/pkg/runtime/schema"
   112  	"sigs.k8s.io/controller-runtime/pkg/scheme"
   113  )
   114  
   115  var (
   116  	// GroupVersion is group version used to register these objects
   117  	GroupVersion = schema.GroupVersion{Group: "getambassador.io", Version: "v2"}
   118  
   119  	// SchemeBuilder is used to add go types to the GroupVersionKind scheme
   120  	SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
   121  
   122  	// AddToScheme adds the types in this group-version to the given scheme.
   123  	AddToScheme = SchemeBuilder.AddToScheme
   124  
   125  	// This is so the generated conversion code will compile.
   126  	localSchemeBuilder = &SchemeBuilder.SchemeBuilder
   127  )
   128  
   129  //////////////////////////////////////////////////////////////////////
   130  // 4. API design guidelines //////////////////////////////////////////
   131  //////////////////////////////////////////////////////////////////////
   132  //
   133  // Ambassador's API has inconsistencies because it has historical
   134  // baggage.  Not all of Ambassador's existing API (or even most of
   135  // it!?) follow these guidelines, but new additions to the API should.
   136  // If/when we advance to getambassador.io/v3 and we can break
   137  // compatibility, these are things that we should apply everywhere.
   138  //
   139  // - Prefer `camelCase` to `snake_case`
   140  //   * Exception: Except for consistency with existing fields in the
   141  //     same resource, or symmetry with identical fields in another
   142  //     resource.
   143  //   * Justification: Kubernetes style is to use camelCase. But
   144  //     historically Ambassador used snake_case for everything.
   145  //
   146  // - Give _every_ field a `json:""` struct tag.
   147  //   * Justification: Marshaling and unmarshaling are key to what we
   148  //     do, and it's critical to carefully define how it happens.
   149  //   * Notes: This is not optional. Do it for _every field_. (It's OK
   150  //     if the tag is literally `json:""` for fields that must never be
   151  //     exposed during marshaling.)
   152  //
   153  // - Prefer `*int`, `*bool`, and `*BoolOrString`, rather than just
   154  //   `int`, `bool`, and `BoolOrString`.
   155  //   * Justification: The Ambassador API is rooted in Python, where
   156  //     it is always possible to tell if a given element was present in
   157  //     in a CRD, or left unset. This is at odds with Go's `omitempty`
   158  //     specifier, which really means "omit if empty _or if set to the
   159  //     default value". For int in particular, this results in a value
   160  //     of 0 being omitted, and for many Ambassador fields, 0 is not
   161  //     the correct default value.
   162  //
   163  //     This resulted in a lot of bugs in the 1.10 timeframe, so be
   164  //     careful going forward.
   165  //
   166  // - Prefer for object references to not support namespacing
   167  //   * Exception: If there's a real use-case for it.
   168  //   * Justification: Most native Kubernetes resources don't support
   169  //     referencing things in a different namespace.  We should be
   170  //     opinionated and not support it either, unless there's a good
   171  //     reason to in a specific case.
   172  //
   173  // - Prefer to use `corev1.LocalObjectReference` or
   174  //   `corev1.SecretReference` references instead of
   175  //   `{name}.{namespace}` strings.
   176  //   * Justification: The `{name}.{namespace}` thing evolved "an
   177  //     opaque DNS name" in the `service` field of Mappings, and that
   178  //     was generalized to other things.  Outside of the context of
   179  //     "this is usable as a DNS name to make a request to", it's just
   180  //     confusing and introduces needless ambiguity.  Nothing other
   181  //     than Ambassador uses that notation.
   182  //   * Notes: For things that don't support cross-namespace references
   183  //     (see above), use LocalObjectReference; if you really must
   184  //     support cross-namespace references, then use SecretReference.
   185  //
   186  // - Prefer to use `metav1.Duration` fields instead of "_s" or "_ms"
   187  //   numeric fields.
   188  //
   189  // - Don't have Ambassador populate anything in the `.spec` or
   190  //   `.metadata` of something a user might edit, only let Ambassador
   191  //   set things in the `.status`.
   192  //   * Exception: If Ambassador 100% owns the resource and a user will
   193  //     never edit it.
   194  //   * Notes: I didn't write "Prefer" on this one.  Don't violate it.
   195  //     Just don't do it.  Ever.  Designing the Host resource in
   196  //     violation of this was a HUGE mistake and one that I regret very
   197  //     much.  Learn from my mistakes.
   198  //   * Justification: Having Ambassador-set things in a subresource
   199  //     from user-set things:
   200  //     1. avoids races between the user updating the spec and us
   201  //        updating the status
   202  //     2. allows watt/whatever to only pay attention to
   203  //        .metadata.generation instead of .metadata.resourceVersion;
   204  //        avoiding pointless reconfigures.
   205  //     3. allows the RBAC to be simpler
   206  //     4. avoids the whole class of bugs where we need to make sure
   207  //        that everything round-trips correctly
   208  //     5. provides clarity on which things a user is expected to know
   209  //        how to fill in
   210  

View as plain text