github.com/cloudposse/helm@v2.2.3+incompatible/pkg/helm/client.go (about) 1 /* 2 Copyright 2016 The Kubernetes Authors All rights reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package helm // import "k8s.io/helm/pkg/helm" 18 19 import ( 20 "io" 21 22 "golang.org/x/net/context" 23 "google.golang.org/grpc" 24 25 "k8s.io/helm/pkg/chartutil" 26 "k8s.io/helm/pkg/proto/hapi/chart" 27 rls "k8s.io/helm/pkg/proto/hapi/services" 28 ) 29 30 // Client manages client side of the helm-tiller protocol 31 type Client struct { 32 opts options 33 } 34 35 // NewClient creates a new client. 36 func NewClient(opts ...Option) *Client { 37 var c Client 38 return c.Option(opts...) 39 } 40 41 // Option configures the helm client with the provided options 42 func (h *Client) Option(opts ...Option) *Client { 43 for _, opt := range opts { 44 opt(&h.opts) 45 } 46 return h 47 } 48 49 // ListReleases lists the current releases. 50 func (h *Client) ListReleases(opts ...ReleaseListOption) (*rls.ListReleasesResponse, error) { 51 for _, opt := range opts { 52 opt(&h.opts) 53 } 54 req := &h.opts.listReq 55 ctx := NewContext() 56 57 if h.opts.before != nil { 58 if err := h.opts.before(ctx, req); err != nil { 59 return nil, err 60 } 61 } 62 return h.list(ctx, req) 63 } 64 65 // InstallRelease loads a chart from chstr, installs it and returns the release response. 66 func (h *Client) InstallRelease(chstr, ns string, opts ...InstallOption) (*rls.InstallReleaseResponse, error) { 67 // load the chart to install 68 chart, err := chartutil.Load(chstr) 69 if err != nil { 70 return nil, err 71 } 72 73 return h.InstallReleaseFromChart(chart, ns, opts...) 74 } 75 76 // InstallReleaseFromChart installs a new chart and returns the release response. 77 func (h *Client) InstallReleaseFromChart(chart *chart.Chart, ns string, opts ...InstallOption) (*rls.InstallReleaseResponse, error) { 78 // apply the install options 79 for _, opt := range opts { 80 opt(&h.opts) 81 } 82 req := &h.opts.instReq 83 req.Chart = chart 84 req.Namespace = ns 85 req.DryRun = h.opts.dryRun 86 req.DisableHooks = h.opts.disableHooks 87 req.ReuseName = h.opts.reuseName 88 ctx := NewContext() 89 90 if h.opts.before != nil { 91 if err := h.opts.before(ctx, req); err != nil { 92 return nil, err 93 } 94 } 95 err := chartutil.ProcessRequirementsEnabled(req.Chart, req.Values) 96 if err != nil { 97 return nil, err 98 } 99 100 return h.install(ctx, req) 101 } 102 103 // DeleteRelease uninstalls a named release and returns the response. 104 func (h *Client) DeleteRelease(rlsName string, opts ...DeleteOption) (*rls.UninstallReleaseResponse, error) { 105 // apply the uninstall options 106 for _, opt := range opts { 107 opt(&h.opts) 108 } 109 110 if h.opts.dryRun { 111 // In the dry run case, just see if the release exists 112 r, err := h.ReleaseContent(rlsName) 113 if err != nil { 114 return &rls.UninstallReleaseResponse{}, err 115 } 116 return &rls.UninstallReleaseResponse{Release: r.Release}, nil 117 } 118 119 req := &h.opts.uninstallReq 120 req.Name = rlsName 121 req.DisableHooks = h.opts.disableHooks 122 ctx := NewContext() 123 124 if h.opts.before != nil { 125 if err := h.opts.before(ctx, req); err != nil { 126 return nil, err 127 } 128 } 129 return h.delete(ctx, req) 130 } 131 132 // UpdateRelease loads a chart from chstr and updates a release to a new/different chart 133 func (h *Client) UpdateRelease(rlsName string, chstr string, opts ...UpdateOption) (*rls.UpdateReleaseResponse, error) { 134 // load the chart to update 135 chart, err := chartutil.Load(chstr) 136 if err != nil { 137 return nil, err 138 } 139 140 return h.UpdateReleaseFromChart(rlsName, chart, opts...) 141 } 142 143 // UpdateReleaseFromChart updates a release to a new/different chart 144 func (h *Client) UpdateReleaseFromChart(rlsName string, chart *chart.Chart, opts ...UpdateOption) (*rls.UpdateReleaseResponse, error) { 145 146 // apply the update options 147 for _, opt := range opts { 148 opt(&h.opts) 149 } 150 req := &h.opts.updateReq 151 req.Chart = chart 152 req.DryRun = h.opts.dryRun 153 req.Name = rlsName 154 req.DisableHooks = h.opts.disableHooks 155 req.Recreate = h.opts.recreate 156 req.ResetValues = h.opts.resetValues 157 ctx := NewContext() 158 159 if h.opts.before != nil { 160 if err := h.opts.before(ctx, req); err != nil { 161 return nil, err 162 } 163 } 164 err := chartutil.ProcessRequirementsEnabled(req.Chart, req.Values) 165 if err != nil { 166 return nil, err 167 } 168 169 return h.update(ctx, req) 170 } 171 172 // GetVersion returns the server version 173 func (h *Client) GetVersion(opts ...VersionOption) (*rls.GetVersionResponse, error) { 174 for _, opt := range opts { 175 opt(&h.opts) 176 } 177 req := &rls.GetVersionRequest{} 178 ctx := NewContext() 179 180 if h.opts.before != nil { 181 if err := h.opts.before(ctx, req); err != nil { 182 return nil, err 183 } 184 } 185 return h.version(ctx, req) 186 } 187 188 // RollbackRelease rolls back a release to the previous version 189 func (h *Client) RollbackRelease(rlsName string, opts ...RollbackOption) (*rls.RollbackReleaseResponse, error) { 190 for _, opt := range opts { 191 opt(&h.opts) 192 } 193 req := &h.opts.rollbackReq 194 req.DisableHooks = h.opts.disableHooks 195 req.DryRun = h.opts.dryRun 196 req.Name = rlsName 197 ctx := NewContext() 198 199 if h.opts.before != nil { 200 if err := h.opts.before(ctx, req); err != nil { 201 return nil, err 202 } 203 } 204 return h.rollback(ctx, req) 205 } 206 207 // ReleaseStatus returns the given release's status. 208 func (h *Client) ReleaseStatus(rlsName string, opts ...StatusOption) (*rls.GetReleaseStatusResponse, error) { 209 for _, opt := range opts { 210 opt(&h.opts) 211 } 212 req := &h.opts.statusReq 213 req.Name = rlsName 214 ctx := NewContext() 215 216 if h.opts.before != nil { 217 if err := h.opts.before(ctx, req); err != nil { 218 return nil, err 219 } 220 } 221 return h.status(ctx, req) 222 } 223 224 // ReleaseContent returns the configuration for a given release. 225 func (h *Client) ReleaseContent(rlsName string, opts ...ContentOption) (*rls.GetReleaseContentResponse, error) { 226 for _, opt := range opts { 227 opt(&h.opts) 228 } 229 req := &h.opts.contentReq 230 req.Name = rlsName 231 ctx := NewContext() 232 233 if h.opts.before != nil { 234 if err := h.opts.before(ctx, req); err != nil { 235 return nil, err 236 } 237 } 238 return h.content(ctx, req) 239 } 240 241 // ReleaseHistory returns a release's revision history. 242 func (h *Client) ReleaseHistory(rlsName string, opts ...HistoryOption) (*rls.GetHistoryResponse, error) { 243 for _, opt := range opts { 244 opt(&h.opts) 245 } 246 247 req := &h.opts.histReq 248 req.Name = rlsName 249 ctx := NewContext() 250 251 if h.opts.before != nil { 252 if err := h.opts.before(ctx, req); err != nil { 253 return nil, err 254 } 255 } 256 return h.history(ctx, req) 257 } 258 259 // RunReleaseTest executes a pre-defined test on a release 260 func (h *Client) RunReleaseTest(rlsName string, opts ...ReleaseTestOption) (<-chan *rls.TestReleaseResponse, <-chan error) { 261 for _, opt := range opts { 262 opt(&h.opts) 263 } 264 265 req := &h.opts.testReq 266 req.Name = rlsName 267 ctx := NewContext() 268 269 return h.test(ctx, req) 270 } 271 272 // Executes tiller.ListReleases RPC. 273 func (h *Client) list(ctx context.Context, req *rls.ListReleasesRequest) (*rls.ListReleasesResponse, error) { 274 c, err := grpc.Dial(h.opts.host, grpc.WithInsecure()) 275 if err != nil { 276 return nil, err 277 } 278 defer c.Close() 279 280 rlc := rls.NewReleaseServiceClient(c) 281 s, err := rlc.ListReleases(ctx, req) 282 if err != nil { 283 return nil, err 284 } 285 286 return s.Recv() 287 } 288 289 // Executes tiller.InstallRelease RPC. 290 func (h *Client) install(ctx context.Context, req *rls.InstallReleaseRequest) (*rls.InstallReleaseResponse, error) { 291 c, err := grpc.Dial(h.opts.host, grpc.WithInsecure()) 292 if err != nil { 293 return nil, err 294 } 295 defer c.Close() 296 297 rlc := rls.NewReleaseServiceClient(c) 298 return rlc.InstallRelease(ctx, req) 299 } 300 301 // Executes tiller.UninstallRelease RPC. 302 func (h *Client) delete(ctx context.Context, req *rls.UninstallReleaseRequest) (*rls.UninstallReleaseResponse, error) { 303 c, err := grpc.Dial(h.opts.host, grpc.WithInsecure()) 304 if err != nil { 305 return nil, err 306 } 307 defer c.Close() 308 309 rlc := rls.NewReleaseServiceClient(c) 310 return rlc.UninstallRelease(ctx, req) 311 } 312 313 // Executes tiller.UpdateRelease RPC. 314 func (h *Client) update(ctx context.Context, req *rls.UpdateReleaseRequest) (*rls.UpdateReleaseResponse, error) { 315 c, err := grpc.Dial(h.opts.host, grpc.WithInsecure()) 316 if err != nil { 317 return nil, err 318 } 319 defer c.Close() 320 321 rlc := rls.NewReleaseServiceClient(c) 322 return rlc.UpdateRelease(ctx, req) 323 } 324 325 // Executes tiller.RollbackRelease RPC. 326 func (h *Client) rollback(ctx context.Context, req *rls.RollbackReleaseRequest) (*rls.RollbackReleaseResponse, error) { 327 c, err := grpc.Dial(h.opts.host, grpc.WithInsecure()) 328 if err != nil { 329 return nil, err 330 } 331 defer c.Close() 332 333 rlc := rls.NewReleaseServiceClient(c) 334 return rlc.RollbackRelease(ctx, req) 335 } 336 337 // Executes tiller.GetReleaseStatus RPC. 338 func (h *Client) status(ctx context.Context, req *rls.GetReleaseStatusRequest) (*rls.GetReleaseStatusResponse, error) { 339 c, err := grpc.Dial(h.opts.host, grpc.WithInsecure()) 340 if err != nil { 341 return nil, err 342 } 343 defer c.Close() 344 345 rlc := rls.NewReleaseServiceClient(c) 346 return rlc.GetReleaseStatus(ctx, req) 347 } 348 349 // Executes tiller.GetReleaseContent RPC. 350 func (h *Client) content(ctx context.Context, req *rls.GetReleaseContentRequest) (*rls.GetReleaseContentResponse, error) { 351 c, err := grpc.Dial(h.opts.host, grpc.WithInsecure()) 352 if err != nil { 353 return nil, err 354 } 355 defer c.Close() 356 357 rlc := rls.NewReleaseServiceClient(c) 358 return rlc.GetReleaseContent(ctx, req) 359 } 360 361 // Executes tiller.GetVersion RPC. 362 func (h *Client) version(ctx context.Context, req *rls.GetVersionRequest) (*rls.GetVersionResponse, error) { 363 c, err := grpc.Dial(h.opts.host, grpc.WithInsecure()) 364 if err != nil { 365 return nil, err 366 } 367 defer c.Close() 368 369 rlc := rls.NewReleaseServiceClient(c) 370 return rlc.GetVersion(ctx, req) 371 } 372 373 // Executes tiller.GetHistory RPC. 374 func (h *Client) history(ctx context.Context, req *rls.GetHistoryRequest) (*rls.GetHistoryResponse, error) { 375 c, err := grpc.Dial(h.opts.host, grpc.WithInsecure()) 376 if err != nil { 377 return nil, err 378 } 379 defer c.Close() 380 381 rlc := rls.NewReleaseServiceClient(c) 382 return rlc.GetHistory(ctx, req) 383 } 384 385 // Executes tiller.TestRelease RPC. 386 func (h *Client) test(ctx context.Context, req *rls.TestReleaseRequest) (<-chan *rls.TestReleaseResponse, <-chan error) { 387 errc := make(chan error, 1) 388 c, err := grpc.Dial(h.opts.host, grpc.WithInsecure()) 389 if err != nil { 390 errc <- err 391 return nil, errc 392 } 393 394 ch := make(chan *rls.TestReleaseResponse, 1) 395 go func() { 396 defer close(errc) 397 defer close(ch) 398 defer c.Close() 399 400 rlc := rls.NewReleaseServiceClient(c) 401 s, err := rlc.RunReleaseTest(ctx, req) 402 if err != nil { 403 errc <- err 404 return 405 } 406 407 for { 408 msg, err := s.Recv() 409 if err == io.EOF { 410 return 411 } 412 if err != nil { 413 errc <- err 414 return 415 } 416 ch <- msg 417 } 418 }() 419 420 return ch, errc 421 }