github.com/replicatedhq/ship@v0.55.0/pkg/lifecycle/render/inline/render_test.go (about) 1 package inline 2 3 import ( 4 "context" 5 "fmt" 6 "io/ioutil" 7 "os" 8 "path/filepath" 9 "testing" 10 11 "github.com/replicatedhq/libyaml" 12 "github.com/spf13/afero" 13 "github.com/spf13/viper" 14 "github.com/stretchr/testify/require" 15 16 "github.com/replicatedhq/ship/pkg/api" 17 "github.com/replicatedhq/ship/pkg/lifecycle/render/root" 18 "github.com/replicatedhq/ship/pkg/templates" 19 "github.com/replicatedhq/ship/pkg/test-mocks/state" 20 "github.com/replicatedhq/ship/pkg/testing/logger" 21 ) 22 23 func TestInlineRender(t *testing.T) { 24 type fileStruct struct { 25 contents string 26 path string 27 mode os.FileMode 28 } 29 tests := []struct { 30 name string 31 asset api.InlineAsset 32 meta api.ReleaseMetadata 33 templateContext map[string]interface{} 34 configGroups []libyaml.ConfigGroup 35 expect fileStruct 36 expectErr bool 37 }{ 38 { 39 name: "happy path", 40 asset: api.InlineAsset{ 41 Contents: "hello!", 42 AssetShared: api.AssetShared{ 43 Dest: "foo.txt", 44 }, 45 }, 46 expect: fileStruct{ 47 path: "foo.txt", 48 contents: "hello!", 49 mode: 0644, 50 }, 51 52 meta: api.ReleaseMetadata{}, 53 templateContext: map[string]interface{}{}, 54 configGroups: []libyaml.ConfigGroup{}, 55 }, 56 { 57 name: "templated dest path", 58 asset: api.InlineAsset{ 59 Contents: "hello!", 60 AssetShared: api.AssetShared{ 61 Dest: "{{repl if true}}foo.txt{{repl else}}notfoo.txt{{repl end}}", 62 Mode: os.ModePerm, 63 }, 64 }, 65 expect: fileStruct{ 66 path: "foo.txt", 67 contents: "hello!", 68 mode: os.ModePerm, 69 }, 70 71 meta: api.ReleaseMetadata{}, 72 templateContext: map[string]interface{}{}, 73 configGroups: []libyaml.ConfigGroup{}, 74 }, 75 { 76 name: "absolute dest path", 77 asset: api.InlineAsset{ 78 Contents: "hello!", 79 AssetShared: api.AssetShared{ 80 Dest: "/bin/runc", 81 }, 82 }, 83 84 meta: api.ReleaseMetadata{}, 85 templateContext: map[string]interface{}{}, 86 configGroups: []libyaml.ConfigGroup{}, 87 expectErr: true, 88 }, 89 { 90 name: "parent dir dest path", 91 asset: api.InlineAsset{ 92 Contents: "hello!", 93 AssetShared: api.AssetShared{ 94 Dest: "../../../bin/runc", 95 }, 96 }, 97 98 meta: api.ReleaseMetadata{}, 99 templateContext: map[string]interface{}{}, 100 configGroups: []libyaml.ConfigGroup{}, 101 expectErr: true, 102 }, 103 { 104 name: "odd filemode", 105 asset: api.InlineAsset{ 106 Contents: "hello!", 107 AssetShared: api.AssetShared{ 108 Dest: "foo.txt", 109 Mode: 0543, 110 }, 111 }, 112 expect: fileStruct{ 113 path: "foo.txt", 114 contents: "hello!", 115 mode: 0543, 116 }, 117 118 meta: api.ReleaseMetadata{}, 119 templateContext: map[string]interface{}{}, 120 configGroups: []libyaml.ConfigGroup{}, 121 }, 122 } 123 for _, test := range tests { 124 t.Run(test.name+" aferoFS", func(t *testing.T) { 125 req := require.New(t) 126 testLogger := &logger.TestLogger{T: t} 127 v := viper.New() 128 bb := templates.NewBuilderBuilder(testLogger, v, &state.MockManager{}) 129 rootFs := root.Fs{ 130 Afero: afero.Afero{Fs: afero.NewMemMapFs()}, 131 RootPath: "", 132 } 133 134 renderer := &LocalRenderer{ 135 Logger: testLogger, 136 Viper: v, 137 BuilderBuilder: bb, 138 } 139 140 err := renderer.Execute( 141 rootFs, 142 test.asset, 143 test.meta, 144 test.templateContext, 145 test.configGroups, 146 )(context.Background()) 147 if !test.expectErr { 148 req.NoError(err) 149 } else { 150 req.Error(err) 151 } 152 153 if !test.expectErr { 154 contents, err := rootFs.ReadFile(test.expect.path) 155 req.NoError(err) 156 req.Equal(test.expect.contents, string(contents)) 157 stat, err := rootFs.Stat(test.expect.path) 158 req.NoError(err) 159 req.Equal(test.expect.mode, stat.Mode()) 160 } 161 }) 162 163 t.Run(test.name+" real FS", func(t *testing.T) { 164 req := require.New(t) 165 testLogger := &logger.TestLogger{T: t} 166 v := viper.New() 167 bb := templates.NewBuilderBuilder(testLogger, v, &state.MockManager{}) 168 tempdir, err := ioutil.TempDir("", "inline-render-test") 169 req.NoError(err) 170 defer os.RemoveAll(tempdir) 171 rootFs := root.Fs{ 172 Afero: afero.Afero{Fs: afero.NewBasePathFs(afero.NewOsFs(), tempdir)}, 173 RootPath: "", 174 } 175 176 renderer := &LocalRenderer{ 177 Logger: testLogger, 178 Viper: v, 179 BuilderBuilder: bb, 180 } 181 182 err = renderer.Execute( 183 rootFs, 184 test.asset, 185 test.meta, 186 test.templateContext, 187 test.configGroups, 188 )(context.Background()) 189 if !test.expectErr { 190 req.NoError(err) 191 } else { 192 req.Error(err) 193 } 194 195 if !test.expectErr { 196 contents, err := rootFs.ReadFile(test.expect.path) 197 req.NoError(err) 198 req.Equal(test.expect.contents, string(contents)) 199 stat, err := rootFs.Stat(test.expect.path) 200 req.NoError(err) 201 req.Equal(test.expect.mode, stat.Mode()) 202 } 203 }) 204 } 205 } 206 207 func TestAfero(t *testing.T) { 208 modes := []os.FileMode{ 209 os.ModePerm, 210 0666, 211 0555, 212 0444, 213 0333, 214 0222, 215 0111, 216 0000, 217 0644, 218 0600, 219 0700, 220 0733, 221 0777, 222 0755, 223 } 224 for _, mode := range modes { 225 t.Run(fmt.Sprint(mode)+" afero FS", func(t *testing.T) { 226 req := require.New(t) 227 aferoFS := afero.Afero{Fs: afero.NewMemMapFs()} 228 229 err := aferoFS.WriteFile("test.txt", []byte("Hello, World!"), mode) 230 req.NoError(err) 231 err = aferoFS.Chmod("test.txt", mode) 232 req.NoError(err) 233 234 stat, err := aferoFS.Stat("test.txt") 235 req.NoError(err) 236 237 req.Equal(fmt.Sprint(mode), fmt.Sprint(stat.Mode())) 238 }) 239 240 t.Run(fmt.Sprint(mode)+" real FS", func(t *testing.T) { 241 req := require.New(t) 242 tempdir, err := ioutil.TempDir("", "afero-test") 243 req.NoError(err) 244 defer os.RemoveAll(tempdir) 245 realFS := afero.Afero{Fs: afero.NewBasePathFs(afero.NewOsFs(), tempdir)} 246 247 err = realFS.WriteFile("test.txt", []byte("Hello, World!"), mode) 248 req.NoError(err) 249 err = realFS.Chmod("test.txt", mode) 250 req.NoError(err) 251 252 stat, err := realFS.Stat("test.txt") 253 req.NoError(err) 254 255 req.Equal(fmt.Sprint(mode), fmt.Sprint(stat.Mode())) 256 }) 257 258 t.Run(fmt.Sprint(mode)+" manual FS", func(t *testing.T) { 259 req := require.New(t) 260 tempdir, err := ioutil.TempDir("", "afero-test") 261 req.NoError(err) 262 defer os.RemoveAll(tempdir) 263 264 err = ioutil.WriteFile(filepath.Join(tempdir, "test.txt"), []byte("Hello, World!"), mode) 265 req.NoError(err) 266 err = os.Chmod(filepath.Join(tempdir, "test.txt"), mode) 267 req.NoError(err) 268 stat, err := os.Stat(filepath.Join(tempdir, "test.txt")) 269 req.NoError(err) 270 271 req.Equal(fmt.Sprint(mode), fmt.Sprint(stat.Mode())) 272 }) 273 } 274 }