github.com/joelanford/operator-sdk@v0.8.2/internal/pkg/scaffold/crd_test.go (about)

     1  // Copyright 2018 The Operator-SDK Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package scaffold
    16  
    17  import (
    18  	"path/filepath"
    19  	"testing"
    20  
    21  	testutil "github.com/operator-framework/operator-sdk/internal/pkg/scaffold/internal/testutil"
    22  	"github.com/operator-framework/operator-sdk/internal/util/diffutil"
    23  	"github.com/operator-framework/operator-sdk/internal/util/fileutil"
    24  
    25  	"github.com/spf13/afero"
    26  )
    27  
    28  func TestCRDGoProject(t *testing.T) {
    29  	r, err := NewResource("cache.example.com/v1alpha1", "Memcached")
    30  	if err != nil {
    31  		t.Fatal(err)
    32  	}
    33  	s, buf := setupScaffoldAndWriter()
    34  	s.Fs = afero.NewMemMapFs()
    35  	cfg, err := setupTestFrameworkConfig()
    36  	if err != nil {
    37  		t.Fatal(err)
    38  	}
    39  
    40  	err = testutil.WriteOSPathToFS(afero.NewOsFs(), s.Fs, cfg.AbsProjectPath)
    41  	if err != nil {
    42  		t.Fatal(err)
    43  	}
    44  
    45  	err = s.Execute(cfg, &CRD{Resource: r, IsOperatorGo: true})
    46  	if err != nil {
    47  		t.Fatalf("Failed to execute the scaffold: (%v)", err)
    48  	}
    49  
    50  	if crdGoExp != buf.String() {
    51  		diffs := diffutil.Diff(crdGoExp, buf.String())
    52  		t.Fatalf("Expected vs actual differs.\n%v", diffs)
    53  	}
    54  }
    55  
    56  const crdGoExp = `apiVersion: apiextensions.k8s.io/v1beta1
    57  kind: CustomResourceDefinition
    58  metadata:
    59    name: memcacheds.cache.example.com
    60  spec:
    61    group: cache.example.com
    62    names:
    63      kind: Memcached
    64      listKind: MemcachedList
    65      plural: memcacheds
    66      singular: memcached
    67    scope: Namespaced
    68    subresources:
    69      status: {}
    70    validation:
    71      openAPIV3Schema:
    72        properties:
    73          apiVersion:
    74            description: 'APIVersion defines the versioned schema of this representation
    75              of an object. Servers should convert recognized schemas to the latest
    76              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources'
    77            type: string
    78          kind:
    79            description: 'Kind is a string value representing the REST resource this
    80              object represents. Servers may infer this from the endpoint the client
    81              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds'
    82            type: string
    83          metadata:
    84            type: object
    85          spec:
    86            properties:
    87              size:
    88                description: Size is the size of the memcached deployment
    89                format: int32
    90                type: integer
    91            required:
    92            - size
    93            type: object
    94          status:
    95            properties:
    96              nodes:
    97                description: Nodes are the names of the memcached pods
    98                items:
    99                  type: string
   100                type: array
   101            required:
   102            - nodes
   103            type: object
   104    version: v1alpha1
   105    versions:
   106    - name: v1alpha1
   107      served: true
   108      storage: true
   109  `
   110  
   111  func TestCRDNonGoProject(t *testing.T) {
   112  	s, buf := setupScaffoldAndWriter()
   113  	s.Fs = afero.NewMemMapFs()
   114  
   115  	r, err := NewResource(appApiVersion, appKind)
   116  	if err != nil {
   117  		t.Fatal(err)
   118  	}
   119  
   120  	crd := &CRD{Resource: r}
   121  	i, err := crd.GetInput()
   122  	if err != nil {
   123  		t.Fatal(err)
   124  	}
   125  	cfg, err := setupTestFrameworkConfig()
   126  	if err != nil {
   127  		t.Fatal(err)
   128  	}
   129  
   130  	path := filepath.Join(cfg.AbsProjectPath, i.Path)
   131  	err = afero.WriteFile(s.Fs, path, []byte(crdNonGoExp), fileutil.DefaultFileMode)
   132  	if err != nil {
   133  		t.Fatal(err)
   134  	}
   135  
   136  	if err = s.Execute(cfg, crd); err != nil {
   137  		t.Fatalf("Failed to execute the scaffold: (%v)", err)
   138  	}
   139  
   140  	if crdNonGoExp != buf.String() {
   141  		diffs := diffutil.Diff(crdNonGoExp, buf.String())
   142  		t.Fatalf("Expected vs actual differs.\n%v", diffs)
   143  	}
   144  }
   145  
   146  // crdNonGoExp contains a simple validation block to make sure manually-added
   147  // validation is not overwritten. Non-go projects don't have the luxury of
   148  // kubebuilder annotations.
   149  const crdNonGoExp = `apiVersion: apiextensions.k8s.io/v1beta1
   150  kind: CustomResourceDefinition
   151  metadata:
   152    name: appservices.app.example.com
   153  spec:
   154    group: app.example.com
   155    names:
   156      kind: AppService
   157      listKind: AppServiceList
   158      plural: appservices
   159      singular: appservice
   160    scope: Namespaced
   161    subresources:
   162      status: {}
   163    validation:
   164      openAPIV3Schema:
   165        properties:
   166          spec:
   167            properties:
   168              size:
   169                format: int32
   170                type: integer
   171            required:
   172            - size
   173            type: object
   174          status:
   175            properties:
   176              nodes:
   177                items:
   178                  type: string
   179                type: array
   180            required:
   181            - nodes
   182            type: object
   183    version: v1alpha1
   184    versions:
   185    - name: v1alpha1
   186      served: true
   187      storage: true
   188  `