Compare commits

...

12 Commits

Author SHA1 Message Date
Jesse Suen
ff87d8cb9e Fix issue where helm hooks were being deployed as part of sync (issue #605) 2018-09-17 11:39:10 -07:00
Jesse Suen
da1373e953 Support helm charts with dependencies and namespace sensitivity (issue #582) 2018-09-17 11:38:19 -07:00
Alexander Matyushentsev
53603b17c1 Issue #584 - ArgoCD fails to deploy resources list (#598) 2018-09-14 13:53:48 -07:00
Jesse Suen
13c15988cd Fix comparison failure when app contains unregistered custom resource (issue #583) (#596) 2018-09-13 14:03:30 -07:00
Jesse Suen
6375efe23e Fix race conditions in kube.GetResourcesWithLabel and DeleteResourceWithLabel (issue #587) (#593) 2018-09-13 13:59:52 -07:00
Conor Fennell
9a74698308 Issue #577 - Add rbac non resource url policy for argocd-manager-role (#578)
* Add rbac non resource url policy for argocd-manager-role
* allow all non resource urls to be added through rbac
2018-09-13 00:04:10 -07:00
Alexander Matyushentsev
3e374988ce Issue 499 - fileFiles path should be relative to app directory (#552) 2018-09-12 23:58:31 -07:00
Jesse Suen
e5eefa2b94 Fix app sync / wait panic in CLI 2018-09-12 01:27:25 -07:00
Jesse Suen
5293527a0c Downgrade ksonnet from v0.12.0 to v0.11.0 due to quote unescape regression 2018-09-12 01:27:25 -07:00
Jesse Suen
973f736b37 Update manifests to point to v0.8.1 2018-09-10 14:11:42 -07:00
Jesse Suen
8c91935575 Fix controller hot loop when app source contains bad manifests (issue #568) (#570) 2018-09-10 11:00:19 -07:00
Jesse Suen
f82bb53a86 Fix issue where branch checkout did not have accurate git tree state (issue #567) (#569) 2018-09-10 11:00:02 -07:00
44 changed files with 1530 additions and 125 deletions

View File

@@ -1,5 +1,20 @@
# Changelog
## v0.8.2 (2018-09-12)
- Downgrade ksonnet from v0.12.0 to v0.11.0 due to quote unescape regression
- Fix CLI panic when performing an initial `argocd sync/wait`
## v0.8.1 (2018-09-10)
+ [UI] Support selection of helm values files in App creation wizard (issue #499)
+ [UI] Support specifying source revision in App creation wizard allow (issue #503)
+ [UI] Improve resource diff rendering (issue #457)
+ [UI] Indicate number of ready containers in pod (issue #539)
+ [UI] Indicate when app is overriding parameters (issue #503)
+ [UI] Provide a YAML view of resources (issue #396)
- Fix issue where changes were not pulled when tracking a branch (issue #567)
- Fix controller hot loop when app source contains bad manifests (issue #568)
- [UI] Fix issue where projects filter does not work when application got changed
## v0.8.0 (2018-09-04)
### Notes about upgrading from v0.7

View File

@@ -49,7 +49,7 @@ RUN curl -L -o /usr/local/bin/kubectl -LO https://storage.googleapis.com/kuberne
# Option 1: build ksonnet ourselves
#RUN go get -v -u github.com/ksonnet/ksonnet && mv ${GOPATH}/bin/ksonnet /usr/local/bin/ks
# Option 2: use official tagged ksonnet release
ENV KSONNET_VERSION=0.12.0
ENV KSONNET_VERSION=0.11.0
RUN wget https://github.com/ksonnet/ksonnet/releases/download/v${KSONNET_VERSION}/ks_${KSONNET_VERSION}_linux_amd64.tar.gz && \
tar -C /tmp/ -xf ks_${KSONNET_VERSION}_linux_amd64.tar.gz && \
mv /tmp/ks_${KSONNET_VERSION}_linux_amd64/ks /usr/local/bin/ks
@@ -123,6 +123,9 @@ RUN ln -s /usr/local/bin/argocd /argocd && \
ln -s /usr/local/bin/argocd-repo-server /argocd-repo-server
USER argocd
RUN helm init --client-only
WORKDIR /home/argocd
ARG BINARY
CMD ${BINARY}

11
Gopkg.lock generated
View File

@@ -356,7 +356,7 @@
revision = "e09c5db296004fbe3f74490e84dcd62c3c5ddb1b"
[[projects]]
digest = "1:b3679b7aa6d7243a170d5f43810e0f4a7c3a2120340069f7a077625c51c83fd9"
digest = "1:14d826ee25139b4674e9768ac287a135f4e7c14e1134a5b15e4e152edfd49f41"
name = "github.com/google/go-jsonnet"
packages = [
".",
@@ -364,7 +364,7 @@
"parser",
]
pruneopts = ""
revision = "v0.11.2"
revision = "dfddf2b4e3aec377b0dcdf247ff92e7d078b8179"
[[projects]]
branch = "master"
@@ -475,7 +475,7 @@
revision = "ae77be60afb1dcacde03767a8c37337fad28ac14"
[[projects]]
digest = "1:f4975a8aa19d1a4e512cfebf9a2c3751faedd8939be80d193d157463b47eb334"
digest = "1:2fe45da14d25bce0a58c5a991967149cc5d07f94be327b928a9fd306466815a3"
name = "github.com/ksonnet/ksonnet"
packages = [
"metadata/params",
@@ -491,11 +491,10 @@
"pkg/util/jsonnet",
"pkg/util/kslib",
"pkg/util/strings",
"pkg/util/version",
]
pruneopts = ""
revision = "5b4917a292a76a62e3d97852279575293ba73b50"
version = "v0.12.0"
revision = "e943ae55d4fe256c8330a047ce8426ad9dac110c"
version = "v0.11.0"
[[projects]]
digest = "1:a345c560e5609bd71b1f54993f3b087ca45eb0e6226886c642ce519de81896cb"

View File

@@ -46,7 +46,7 @@ required = [
[[constraint]]
name = "github.com/ksonnet/ksonnet"
version = "v0.12.0"
version = "v0.11.0"
[[constraint]]
name = "github.com/gobuffalo/packr"

View File

@@ -1,4 +1,4 @@
controller: go run ./cmd/argocd-application-controller/main.go
api-server: go run ./cmd/argocd-server/main.go --insecure
api-server: go run ./cmd/argocd-server/main.go --insecure --disable-auth
repo-server: go run ./cmd/argocd-repo-server/main.go --loglevel debug
dex: sh -c "go run ./cmd/argocd-util/main.go gendexcfg -o `pwd`/dist/dex.yaml && docker run --rm -p 5556:5556 -p 5557:5557 -v `pwd`/dist/dex.yaml:/dex.yaml quay.io/coreos/dex:v2.10.0 serve /dex.yaml"

View File

@@ -1 +1 @@
0.8.0
0.8.2

View File

@@ -911,10 +911,12 @@ func calculateResourceStates(app *argoappv1.Application) map[string]*resourceSta
}
var opResult *argoappv1.SyncOperationResult
if app.Status.OperationState.SyncResult != nil {
opResult = app.Status.OperationState.SyncResult
} else if app.Status.OperationState.RollbackResult != nil {
opResult = app.Status.OperationState.SyncResult
if app.Status.OperationState != nil {
if app.Status.OperationState.SyncResult != nil {
opResult = app.Status.OperationState.SyncResult
} else if app.Status.OperationState.RollbackResult != nil {
opResult = app.Status.OperationState.SyncResult
}
}
if opResult == nil {
return resStates

View File

@@ -102,4 +102,8 @@ var ArgoCDManagerPolicyRules = []rbacv1.PolicyRule{
Resources: []string{"*"},
Verbs: []string{"*"},
},
{
NonResourceURLs: []string{"*"},
Verbs: []string{"*"},
},
}

View File

@@ -487,13 +487,14 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo
// Returns true if application never been compared, has changed or comparison result has expired.
func (ctrl *ApplicationController) needRefreshAppStatus(app *appv1.Application, statusRefreshTimeout time.Duration) bool {
var reason string
expired := app.Status.ComparisonResult.ComparedAt.Add(statusRefreshTimeout).Before(time.Now().UTC())
if ctrl.isRefreshForced(app.Name) {
reason = "force refresh"
} else if app.Status.ComparisonResult.Status == appv1.ComparisonStatusUnknown {
} else if app.Status.ComparisonResult.Status == appv1.ComparisonStatusUnknown && expired {
reason = "comparison status unknown"
} else if !app.Spec.Source.Equals(app.Status.ComparisonResult.ComparedTo) {
reason = "spec.source differs"
} else if app.Status.ComparisonResult.ComparedAt.Add(statusRefreshTimeout).Before(time.Now().UTC()) {
} else if expired {
reason = fmt.Sprintf("comparison expired. comparedAt: %v, expiry: %v", app.Status.ComparisonResult.ComparedAt, statusRefreshTimeout)
}
if reason != "" {

View File

@@ -7,6 +7,7 @@ import (
"time"
log "github.com/sirupsen/logrus"
apierr "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/types"
@@ -121,6 +122,7 @@ func (s *ksonnetAppStateManager) getTargetObjs(app *v1alpha1.Application, revisi
ComponentParameterOverrides: mfReqOverrides,
AppLabel: app.Name,
ValueFiles: app.Spec.Source.ValuesFiles,
Namespace: app.Spec.Destination.Namespace,
})
if err != nil {
return nil, nil, err
@@ -188,11 +190,15 @@ func (s *ksonnetAppStateManager) getLiveObjs(app *v1alpha1.Application, targetOb
}
apiResource, err := kubeutil.ServerResourceForGroupVersionKind(disco, gvk)
if err != nil {
return nil, nil, err
}
liveObj, err = kubeutil.GetLiveResource(dclient, targetObj, apiResource, app.Spec.Destination.Namespace)
if err != nil {
return nil, nil, err
if !apierr.IsNotFound(err) {
return nil, nil, err
}
// If we get here, the app is comprised of a custom resource which has yet to be registered
} else {
liveObj, err = kubeutil.GetLiveResource(dclient, targetObj, apiResource, app.Spec.Destination.Namespace)
if err != nil {
return nil, nil, err
}
}
}
controlledLiveObj[i] = liveObj

52
controller/state_test.go Normal file
View File

@@ -0,0 +1,52 @@
package controller
import (
"testing"
"github.com/ghodss/yaml"
"github.com/stretchr/testify/assert"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
var podManifest = []byte(`
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- image: nginx:1.7.9
name: nginx
resources:
requests:
cpu: 0.2
`)
func newPod() *unstructured.Unstructured {
var un unstructured.Unstructured
err := yaml.Unmarshal(podManifest, &un)
if err != nil {
panic(err)
}
return &un
}
func TestIsHook(t *testing.T) {
pod := newPod()
assert.False(t, isHook(pod))
pod.SetAnnotations(map[string]string{"helm.sh/hook": "post-install"})
assert.True(t, isHook(pod))
pod = newPod()
pod.SetAnnotations(map[string]string{"argocd.argoproj.io/hook": "PreSync"})
assert.True(t, isHook(pod))
pod = newPod()
pod.SetAnnotations(map[string]string{"argocd.argoproj.io/hook": "Skip"})
assert.False(t, isHook(pod))
pod = newPod()
pod.SetAnnotations(map[string]string{"argocd.argoproj.io/hook": "Unknown"})
assert.False(t, isHook(pod))
}

View File

@@ -627,7 +627,7 @@ func isHelmHook(obj *unstructured.Unstructured) bool {
if annotations == nil {
return false
}
_, ok := annotations[common.AnnotationHook]
_, ok := annotations[common.AnnotationHelmHook]
return ok
}

View File

@@ -14,6 +14,6 @@ spec:
spec:
containers:
- command: [/argocd-application-controller, --repo-server, 'argocd-repo-server:8081']
image: argoproj/argocd-application-controller:v0.8.0
image: argoproj/argocd-application-controller:v0.8.2
name: application-controller
serviceAccountName: application-controller

View File

@@ -15,20 +15,20 @@ spec:
serviceAccountName: argocd-server
initContainers:
- name: copyutil
image: argoproj/argocd-server:v0.8.0
image: argoproj/argocd-server:v0.8.2
command: [cp, /argocd-util, /shared]
volumeMounts:
- mountPath: /shared
name: static-files
- name: ui
image: argoproj/argocd-ui:v0.8.0
image: argoproj/argocd-ui:v0.8.2
command: [cp, -r, /app, /shared]
volumeMounts:
- mountPath: /shared
name: static-files
containers:
- name: argocd-server
image: argoproj/argocd-server:v0.8.0
image: argoproj/argocd-server:v0.8.2
command: [/argocd-server, --staticassets, /shared/app, --repo-server, 'argocd-repo-server:8081']
volumeMounts:
- mountPath: /shared

View File

@@ -12,9 +12,15 @@ spec:
labels:
app: argocd-repo-server
spec:
automountServiceAccountToken: false
containers:
- name: argocd-repo-server
image: argoproj/argocd-repo-server:v0.8.0
image: argoproj/argocd-repo-server:v0.8.2
command: [/argocd-repo-server]
ports:
- containerPort: 8081
- containerPort: 8081
readinessProbe:
tcpSocket:
port: 8081
initialDelaySeconds: 5
periodSeconds: 10

View File

@@ -165,7 +165,7 @@ spec:
spec:
containers:
- command: [/argocd-application-controller, --repo-server, 'argocd-repo-server:8081']
image: argoproj/argocd-application-controller:v0.8.0
image: argoproj/argocd-application-controller:v0.8.2
name: application-controller
serviceAccountName: application-controller
---
@@ -241,20 +241,20 @@ spec:
serviceAccountName: argocd-server
initContainers:
- name: copyutil
image: argoproj/argocd-server:v0.8.0
image: argoproj/argocd-server:v0.8.2
command: [cp, /argocd-util, /shared]
volumeMounts:
- mountPath: /shared
name: static-files
- name: ui
image: argoproj/argocd-ui:v0.8.0
image: argoproj/argocd-ui:v0.8.2
command: [cp, -r, /app, /shared]
volumeMounts:
- mountPath: /shared
name: static-files
containers:
- name: argocd-server
image: argoproj/argocd-server:v0.8.0
image: argoproj/argocd-server:v0.8.2
command: [/argocd-server, --staticassets, /shared/app, --repo-server, 'argocd-repo-server:8081']
volumeMounts:
- mountPath: /shared
@@ -307,7 +307,7 @@ spec:
spec:
containers:
- name: argocd-repo-server
image: argoproj/argocd-repo-server:v0.8.0
image: argoproj/argocd-repo-server:v0.8.2
command: [/argocd-repo-server]
ports:
- containerPort: 8081

View File

@@ -16,6 +16,7 @@ import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"github.com/argoproj/argo-cd/common"
"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
@@ -82,7 +83,7 @@ func (s *Service) ListDir(ctx context.Context, q *ListDirRequest) (*FileList, er
return &res, nil
}
err = checkoutRevision(gitClient, q.Revision)
err = checkoutRevision(gitClient, commitSHA)
if err != nil {
return nil, err
}
@@ -116,7 +117,11 @@ func (s *Service) GetFile(ctx context.Context, q *GetFileRequest) (*GetFileRespo
if err != nil {
return nil, err
}
err = checkoutRevision(gitClient, q.Revision)
commitSHA, err := gitClient.LsRemote(q.Revision)
if err != nil {
return nil, err
}
err = checkoutRevision(gitClient, commitSHA)
if err != nil {
return nil, err
}
@@ -165,7 +170,7 @@ func (s *Service) GenerateManifest(c context.Context, q *ManifestRequest) (*Mani
log.Infof("manifest cache miss: %s", cacheKey)
}
err = checkoutRevision(gitClient, q.Revision)
err = checkoutRevision(gitClient, commitSHA)
if err != nil {
return nil, err
}
@@ -192,7 +197,7 @@ func (s *Service) GenerateManifest(c context.Context, q *ManifestRequest) (*Mani
func generateManifests(appPath string, q *ManifestRequest) (*ManifestResponse, error) {
var targetObjs []*unstructured.Unstructured
var params []*v1alpha1.ComponentParameter
var env *app.EnvironmentConfig
var env *app.EnvironmentSpec
var err error
appSourceType := IdentifyAppSourceTypeByAppDir(appPath)
@@ -201,7 +206,11 @@ func generateManifests(appPath string, q *ManifestRequest) (*ManifestResponse, e
targetObjs, params, env, err = ksShow(appPath, q.Environment, q.ComponentParameterOverrides)
case AppSourceHelm:
h := helm.NewHelmApp(appPath)
targetObjs, err = h.Template(q.AppLabel, q.ValueFiles, q.ComponentParameterOverrides)
err = h.DependencyBuild()
if err != nil {
return nil, err
}
targetObjs, err = h.Template(q.AppLabel, q.Namespace, q.ValueFiles, q.ComponentParameterOverrides)
if err != nil {
return nil, err
}
@@ -218,21 +227,40 @@ func generateManifests(appPath string, q *ManifestRequest) (*ManifestResponse, e
if err != nil {
return nil, err
}
// TODO(jessesuen): we need to sort objects based on their dependency order of creation
manifests := make([]string, len(targetObjs))
for i, target := range targetObjs {
if q.AppLabel != "" {
err = kube.SetLabel(target, common.LabelApplicationName, q.AppLabel)
manifests := make([]string, 0)
for _, obj := range targetObjs {
var targets []*unstructured.Unstructured
if obj.IsList() {
err = obj.EachListItem(func(object runtime.Object) error {
unstructuredObj, ok := object.(*unstructured.Unstructured)
if ok {
targets = append(targets, unstructuredObj)
return nil
} else {
return fmt.Errorf("resource list item has unexpected type")
}
})
if err != nil {
return nil, err
}
} else {
targets = []*unstructured.Unstructured{obj}
}
manifestStr, err := json.Marshal(target.Object)
if err != nil {
return nil, err
for _, target := range targets {
if q.AppLabel != "" {
err = kube.SetLabel(target, common.LabelApplicationName, q.AppLabel)
if err != nil {
return nil, err
}
}
manifestStr, err := json.Marshal(target.Object)
if err != nil {
return nil, err
}
manifests = append(manifests, string(manifestStr))
}
manifests[i] = string(manifestStr)
}
res := ManifestResponse{
@@ -280,16 +308,12 @@ func IdentifyAppSourceTypeByAppPath(appFilePath string) AppSourceType {
}
// checkoutRevision is a convenience function to initialize a repo, fetch, and checkout a revision
func checkoutRevision(gitClient git.Client, revision string) error {
func checkoutRevision(gitClient git.Client, commitSHA string) error {
err := gitClient.Fetch()
if err != nil {
return err
}
err = gitClient.Reset()
if err != nil {
log.Warn(err)
}
err = gitClient.Checkout(revision)
err = gitClient.Checkout(commitSHA)
if err != nil {
return err
}
@@ -299,7 +323,7 @@ func checkoutRevision(gitClient git.Client, revision string) error {
func manifestCacheKey(commitSHA string, q *ManifestRequest) string {
pStr, _ := json.Marshal(q.ComponentParameterOverrides)
valuesFiles := strings.Join(q.ValueFiles, ",")
return fmt.Sprintf("mfst|%s|%s|%s|%s|%s|%s", q.AppLabel, q.Path, q.Environment, commitSHA, string(pStr), valuesFiles)
return fmt.Sprintf("mfst|%s|%s|%s|%s|%s|%s|%s", q.AppLabel, q.Path, q.Environment, commitSHA, string(pStr), valuesFiles, q.Namespace)
}
func listDirCacheKey(commitSHA string, q *ListDirRequest) string {
@@ -307,7 +331,7 @@ func listDirCacheKey(commitSHA string, q *ListDirRequest) string {
}
// ksShow runs `ks show` in an app directory after setting any component parameter overrides
func ksShow(appPath, envName string, overrides []*v1alpha1.ComponentParameter) ([]*unstructured.Unstructured, []*v1alpha1.ComponentParameter, *app.EnvironmentConfig, error) {
func ksShow(appPath, envName string, overrides []*v1alpha1.ComponentParameter) ([]*unstructured.Unstructured, []*v1alpha1.ComponentParameter, *app.EnvironmentSpec, error) {
ksApp, err := ksonnet.NewKsonnetApp(appPath)
if err != nil {
return nil, nil, nil, status.Errorf(codes.FailedPrecondition, "unable to load application from %s: %v", appPath, err)

View File

@@ -50,6 +50,7 @@ type ManifestRequest struct {
AppLabel string `protobuf:"bytes,5,opt,name=appLabel,proto3" json:"appLabel,omitempty"`
ComponentParameterOverrides []*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.ComponentParameter `protobuf:"bytes,6,rep,name=componentParameterOverrides" json:"componentParameterOverrides,omitempty"`
ValueFiles []string `protobuf:"bytes,7,rep,name=valueFiles" json:"valueFiles,omitempty"`
Namespace string `protobuf:"bytes,8,opt,name=namespace,proto3" json:"namespace,omitempty"`
}
func (m *ManifestRequest) Reset() { *m = ManifestRequest{} }
@@ -106,6 +107,13 @@ func (m *ManifestRequest) GetValueFiles() []string {
return nil
}
func (m *ManifestRequest) GetNamespace() string {
if m != nil {
return m.Namespace
}
return ""
}
type ManifestResponse struct {
Manifests []string `protobuf:"bytes,1,rep,name=manifests" json:"manifests,omitempty"`
Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"`
@@ -483,6 +491,12 @@ func (m *ManifestRequest) MarshalTo(dAtA []byte) (int, error) {
i += copy(dAtA[i:], s)
}
}
if len(m.Namespace) > 0 {
dAtA[i] = 0x42
i++
i = encodeVarintRepository(dAtA, i, uint64(len(m.Namespace)))
i += copy(dAtA[i:], m.Namespace)
}
return i, nil
}
@@ -730,6 +744,10 @@ func (m *ManifestRequest) Size() (n int) {
n += 1 + l + sovRepository(uint64(l))
}
}
l = len(m.Namespace)
if l > 0 {
n += 1 + l + sovRepository(uint64(l))
}
return n
}
@@ -1072,6 +1090,35 @@ func (m *ManifestRequest) Unmarshal(dAtA []byte) error {
}
m.ValueFiles = append(m.ValueFiles, string(dAtA[iNdEx:postIndex]))
iNdEx = postIndex
case 8:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Namespace", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRepository
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthRepository
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Namespace = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipRepository(dAtA[iNdEx:])
@@ -1840,41 +1887,42 @@ var (
func init() { proto.RegisterFile("reposerver/repository/repository.proto", fileDescriptorRepository) }
var fileDescriptorRepository = []byte{
// 576 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x54, 0xcd, 0x6e, 0xd3, 0x40,
0x10, 0xae, 0xc9, 0x5f, 0xb3, 0x41, 0xb4, 0xac, 0x22, 0x64, 0x39, 0x51, 0x64, 0x59, 0x02, 0xe5,
0x82, 0xad, 0x84, 0x0b, 0x17, 0x84, 0x04, 0x85, 0x0a, 0xa9, 0x55, 0x91, 0x39, 0xc1, 0x05, 0x6d,
0x9c, 0xc1, 0x59, 0x62, 0xef, 0x2e, 0xbb, 0x1b, 0x4b, 0xbc, 0x03, 0x12, 0x0f, 0xc0, 0x0b, 0x71,
0xe4, 0x11, 0x50, 0x6e, 0x7d, 0x0b, 0xe4, 0x8d, 0x1d, 0x3b, 0x6d, 0xd4, 0x0b, 0xaa, 0xd4, 0xdb,
0xcc, 0x37, 0xb3, 0xf3, 0xcd, 0x7e, 0x33, 0x1a, 0xf4, 0x44, 0x82, 0xe0, 0x0a, 0x64, 0x06, 0x32,
0x30, 0x26, 0xd5, 0x5c, 0x7e, 0xaf, 0x99, 0xbe, 0x90, 0x5c, 0x73, 0x8c, 0x2a, 0xc4, 0xe9, 0xc7,
0x3c, 0xe6, 0x06, 0x0e, 0x72, 0x6b, 0x93, 0xe1, 0x0c, 0x63, 0xce, 0xe3, 0x04, 0x02, 0x22, 0x68,
0x40, 0x18, 0xe3, 0x9a, 0x68, 0xca, 0x99, 0x2a, 0xa2, 0xde, 0xf2, 0xb9, 0xf2, 0x29, 0x37, 0xd1,
0x88, 0x4b, 0x08, 0xb2, 0x49, 0x10, 0x03, 0x03, 0x49, 0x34, 0xcc, 0x8b, 0x9c, 0x77, 0x31, 0xd5,
0x8b, 0xd5, 0xcc, 0x8f, 0x78, 0x1a, 0x10, 0x69, 0x28, 0xbe, 0x1a, 0xe3, 0x69, 0x34, 0x0f, 0xc4,
0x32, 0xce, 0x1f, 0xab, 0x80, 0x08, 0x91, 0xd0, 0xc8, 0x14, 0x0f, 0xb2, 0x09, 0x49, 0xc4, 0x82,
0x5c, 0x2b, 0xe5, 0xfd, 0x68, 0xa0, 0xa3, 0x73, 0xc2, 0xe8, 0x17, 0x50, 0x3a, 0x84, 0x6f, 0x2b,
0x50, 0x1a, 0x7f, 0x44, 0xcd, 0xfc, 0x13, 0xb6, 0xe5, 0x5a, 0xe3, 0xde, 0xf4, 0x8d, 0x5f, 0xb1,
0xf9, 0x25, 0x9b, 0x31, 0x3e, 0x47, 0x73, 0x5f, 0x2c, 0x63, 0x3f, 0x67, 0xf3, 0x6b, 0x6c, 0x7e,
0xc9, 0xe6, 0x87, 0x5b, 0x2d, 0x42, 0x53, 0x12, 0x3b, 0xe8, 0x50, 0x42, 0x46, 0x15, 0xe5, 0xcc,
0xbe, 0xe7, 0x5a, 0xe3, 0x6e, 0xb8, 0xf5, 0x31, 0x46, 0x4d, 0x41, 0xf4, 0xc2, 0x6e, 0x18, 0xdc,
0xd8, 0xd8, 0x45, 0x3d, 0x60, 0x19, 0x95, 0x9c, 0xa5, 0xc0, 0xb4, 0xdd, 0x34, 0xa1, 0x3a, 0x94,
0x57, 0x24, 0x42, 0x9c, 0x91, 0x19, 0x24, 0x76, 0x6b, 0x53, 0xb1, 0xf4, 0xf1, 0x4f, 0x0b, 0x0d,
0x22, 0x9e, 0x0a, 0xce, 0x80, 0xe9, 0xf7, 0x44, 0x92, 0x14, 0x34, 0xc8, 0x8b, 0x0c, 0xa4, 0xa4,
0x73, 0x50, 0x76, 0xdb, 0x6d, 0x8c, 0x7b, 0xd3, 0xf3, 0xff, 0xf8, 0xe0, 0xeb, 0x6b, 0xd5, 0xc3,
0x9b, 0x18, 0xf1, 0x08, 0xa1, 0x8c, 0x24, 0x2b, 0x78, 0x4b, 0x13, 0x50, 0x76, 0xc7, 0x6d, 0x8c,
0xbb, 0x61, 0x0d, 0xf1, 0x2e, 0x2d, 0x74, 0x5c, 0x8d, 0x43, 0x09, 0xce, 0x14, 0xe0, 0x21, 0xea,
0xa6, 0x05, 0xa6, 0x6c, 0xcb, 0xbc, 0xa9, 0x80, 0x3c, 0xca, 0x48, 0x0a, 0x4a, 0x90, 0x08, 0x0a,
0x4d, 0x2b, 0x00, 0x3f, 0x42, 0xed, 0xcd, 0xd2, 0x16, 0xb2, 0x16, 0xde, 0xce, 0x20, 0x9a, 0x57,
0x06, 0x01, 0xa8, 0x2d, 0xf2, 0xd6, 0x95, 0xdd, 0xba, 0x0d, 0x81, 0x8a, 0xe2, 0xde, 0x2f, 0x0b,
0x3d, 0x38, 0xa3, 0x4a, 0x9f, 0x50, 0x79, 0xf7, 0x36, 0xcf, 0x73, 0xd1, 0x61, 0x3e, 0x92, 0xbc,
0x41, 0xdc, 0x47, 0x2d, 0xaa, 0x21, 0x2d, 0xc5, 0xdf, 0x38, 0xa6, 0xff, 0x53, 0xd0, 0x79, 0xd6,
0x1d, 0xec, 0xff, 0x31, 0x3a, 0xda, 0x36, 0x57, 0xec, 0x11, 0x46, 0xcd, 0x39, 0xd1, 0xc4, 0x74,
0x77, 0x3f, 0x34, 0xf6, 0xf4, 0xd2, 0x42, 0x0f, 0x2b, 0xae, 0x0f, 0x20, 0x33, 0x1a, 0x01, 0xbe,
0x40, 0xc7, 0xa7, 0xc5, 0xa1, 0x28, 0xb7, 0x11, 0x0f, 0xfc, 0xda, 0xad, 0xbb, 0x72, 0x32, 0x9c,
0xe1, 0xfe, 0xe0, 0x86, 0xd8, 0x3b, 0xc0, 0x2f, 0x50, 0xa7, 0x18, 0x35, 0x76, 0xea, 0xa9, 0xbb,
0xf3, 0x77, 0xfa, 0xf5, 0x58, 0x29, 0xbf, 0x77, 0x80, 0x4f, 0x50, 0xa7, 0xf8, 0xcc, 0xee, 0xf3,
0x5d, 0xf9, 0x9d, 0xc1, 0xde, 0x58, 0xd9, 0xc4, 0xab, 0x97, 0xbf, 0xd7, 0x23, 0xeb, 0xcf, 0x7a,
0x64, 0xfd, 0x5d, 0x8f, 0xac, 0x4f, 0x93, 0x9b, 0x8e, 0xe8, 0xde, 0x63, 0x3f, 0x6b, 0x9b, 0x9b,
0xf9, 0xec, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x12, 0x81, 0x49, 0x46, 0x0c, 0x06, 0x00, 0x00,
// 584 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x55, 0xdd, 0x8a, 0xd3, 0x40,
0x14, 0xde, 0x6c, 0xbb, 0xdd, 0x76, 0x2a, 0xee, 0x3a, 0x14, 0x09, 0x69, 0x29, 0x21, 0xa0, 0xf4,
0xc6, 0x84, 0xd6, 0x1b, 0x6f, 0x44, 0xd0, 0xd5, 0x45, 0xd8, 0x65, 0x25, 0x5e, 0xe9, 0x8d, 0x4c,
0xd3, 0x63, 0x3a, 0x36, 0x99, 0x19, 0x67, 0xa6, 0x01, 0x9f, 0xc2, 0x07, 0xf0, 0x0d, 0x7c, 0x12,
0x2f, 0x7d, 0x04, 0xe9, 0xdd, 0xbe, 0x85, 0x64, 0x9a, 0x34, 0x69, 0xb7, 0xec, 0x8d, 0x08, 0x7b,
0x77, 0xe6, 0x3b, 0x27, 0xdf, 0x77, 0xfe, 0x38, 0x41, 0x8f, 0x25, 0x08, 0xae, 0x40, 0x66, 0x20,
0x03, 0x63, 0x52, 0xcd, 0xe5, 0xb7, 0x9a, 0xe9, 0x0b, 0xc9, 0x35, 0xc7, 0xa8, 0x42, 0x9c, 0x5e,
0xcc, 0x63, 0x6e, 0xe0, 0x20, 0xb7, 0xd6, 0x11, 0xce, 0x20, 0xe6, 0x3c, 0x4e, 0x20, 0x20, 0x82,
0x06, 0x84, 0x31, 0xae, 0x89, 0xa6, 0x9c, 0xa9, 0xc2, 0xeb, 0x2d, 0x9e, 0x29, 0x9f, 0x72, 0xe3,
0x8d, 0xb8, 0x84, 0x20, 0x1b, 0x07, 0x31, 0x30, 0x90, 0x44, 0xc3, 0xac, 0x88, 0x79, 0x1b, 0x53,
0x3d, 0x5f, 0x4e, 0xfd, 0x88, 0xa7, 0x01, 0x91, 0x46, 0xe2, 0x8b, 0x31, 0x9e, 0x44, 0xb3, 0x40,
0x2c, 0xe2, 0xfc, 0x63, 0x15, 0x10, 0x21, 0x12, 0x1a, 0x19, 0xf2, 0x20, 0x1b, 0x93, 0x44, 0xcc,
0xc9, 0x0d, 0x2a, 0xef, 0x67, 0x03, 0x9d, 0x5c, 0x12, 0x46, 0x3f, 0x83, 0xd2, 0x21, 0x7c, 0x5d,
0x82, 0xd2, 0xf8, 0x03, 0x6a, 0xe6, 0x45, 0xd8, 0x96, 0x6b, 0x8d, 0xba, 0x93, 0xd7, 0x7e, 0xa5,
0xe6, 0x97, 0x6a, 0xc6, 0xf8, 0x14, 0xcd, 0x7c, 0xb1, 0x88, 0xfd, 0x5c, 0xcd, 0xaf, 0xa9, 0xf9,
0xa5, 0x9a, 0x1f, 0x6e, 0x7a, 0x11, 0x1a, 0x4a, 0xec, 0xa0, 0xb6, 0x84, 0x8c, 0x2a, 0xca, 0x99,
0x7d, 0xe8, 0x5a, 0xa3, 0x4e, 0xb8, 0x79, 0x63, 0x8c, 0x9a, 0x82, 0xe8, 0xb9, 0xdd, 0x30, 0xb8,
0xb1, 0xb1, 0x8b, 0xba, 0xc0, 0x32, 0x2a, 0x39, 0x4b, 0x81, 0x69, 0xbb, 0x69, 0x5c, 0x75, 0x28,
0x67, 0x24, 0x42, 0x5c, 0x90, 0x29, 0x24, 0xf6, 0xd1, 0x9a, 0xb1, 0x7c, 0xe3, 0xef, 0x16, 0xea,
0x47, 0x3c, 0x15, 0x9c, 0x01, 0xd3, 0xef, 0x88, 0x24, 0x29, 0x68, 0x90, 0x57, 0x19, 0x48, 0x49,
0x67, 0xa0, 0xec, 0x96, 0xdb, 0x18, 0x75, 0x27, 0x97, 0xff, 0x50, 0xe0, 0xab, 0x1b, 0xec, 0xe1,
0x6d, 0x8a, 0x78, 0x88, 0x50, 0x46, 0x92, 0x25, 0xbc, 0xa1, 0x09, 0x28, 0xfb, 0xd8, 0x6d, 0x8c,
0x3a, 0x61, 0x0d, 0xc1, 0x03, 0xd4, 0x61, 0x24, 0x05, 0x25, 0x48, 0x04, 0x76, 0xdb, 0x94, 0x53,
0x01, 0xde, 0xb5, 0x85, 0x4e, 0xab, 0x61, 0x29, 0xc1, 0x99, 0x82, 0xfc, 0x93, 0xb4, 0xc0, 0x94,
0x6d, 0x19, 0xc6, 0x0a, 0xd8, 0x26, 0x3c, 0xdc, 0x21, 0xc4, 0x0f, 0x51, 0x6b, 0xbd, 0xd2, 0x45,
0xd3, 0x8b, 0xd7, 0xd6, 0x98, 0x9a, 0x3b, 0x63, 0x02, 0xd4, 0x12, 0x79, 0x61, 0xca, 0x3e, 0xfa,
0x1f, 0xed, 0x2b, 0xc8, 0xbd, 0x1f, 0x16, 0xba, 0x7f, 0x41, 0x95, 0x3e, 0xa3, 0xf2, 0xee, 0xed,
0xa5, 0xe7, 0xa2, 0x76, 0x3e, 0xb0, 0x3c, 0x41, 0xdc, 0x43, 0x47, 0x54, 0x43, 0x5a, 0x36, 0x7f,
0xfd, 0x30, 0xf9, 0x9f, 0x83, 0xce, 0xa3, 0xee, 0x60, 0xfe, 0x8f, 0xd0, 0xc9, 0x26, 0xb9, 0x62,
0x8f, 0x30, 0x6a, 0xce, 0x88, 0x26, 0x26, 0xbb, 0x7b, 0xa1, 0xb1, 0x27, 0xd7, 0x16, 0x7a, 0x50,
0x69, 0xbd, 0x07, 0x99, 0xd1, 0x08, 0xf0, 0x15, 0x3a, 0x3d, 0x2f, 0xce, 0x48, 0xb9, 0x8d, 0xb8,
0xef, 0xd7, 0x2e, 0xe1, 0xce, 0x41, 0x71, 0x06, 0xfb, 0x9d, 0x6b, 0x61, 0xef, 0x00, 0x3f, 0x47,
0xc7, 0xc5, 0xa8, 0xb1, 0x53, 0x0f, 0xdd, 0x9e, 0xbf, 0xd3, 0xab, 0xfb, 0xca, 0xf6, 0x7b, 0x07,
0xf8, 0x0c, 0x1d, 0x17, 0xc5, 0x6c, 0x7f, 0xbe, 0xdd, 0x7e, 0xa7, 0xbf, 0xd7, 0x57, 0x26, 0xf1,
0xf2, 0xc5, 0xaf, 0xd5, 0xd0, 0xfa, 0xbd, 0x1a, 0x5a, 0x7f, 0x56, 0x43, 0xeb, 0xe3, 0xf8, 0xb6,
0x13, 0xbb, 0xf7, 0x57, 0x30, 0x6d, 0x99, 0x8b, 0xfa, 0xf4, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff,
0x22, 0x8e, 0xa1, 0x51, 0x2a, 0x06, 0x00, 0x00,
}

View File

@@ -17,6 +17,7 @@ message ManifestRequest {
string appLabel = 5;
repeated github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.ComponentParameter componentParameterOverrides = 6;
repeated string valueFiles = 7;
string namespace = 8;
}
message ManifestResponse {

View File

@@ -174,6 +174,7 @@ func (s *Server) GetManifests(ctx context.Context, q *ApplicationManifestQuery)
ComponentParameterOverrides: overrides,
AppLabel: a.Name,
ValueFiles: a.Spec.Source.ValuesFiles,
Namespace: a.Spec.Destination.Namespace,
})
if err != nil {
return nil, err

View File

@@ -2,6 +2,7 @@ package repository
import (
"path"
"path/filepath"
"reflect"
"github.com/ghodss/yaml"
@@ -158,15 +159,23 @@ func (s *Server) GetAppDetails(ctx context.Context, q *RepoAppDetailsQuery) (*Re
if err != nil {
return nil, err
}
appDir := path.Dir(q.Path)
valuesFilesRes, err := repoClient.ListDir(ctx, &repository.ListDirRequest{
Revision: revision,
Repo: repo,
Path: path.Join(path.Dir(q.Path), "*values*.yaml"),
Path: path.Join(appDir, "*values*.yaml"),
})
if err != nil {
return nil, err
}
appSpec.ValueFiles = valuesFilesRes.Items
appSpec.ValueFiles = make([]string, len(valuesFilesRes.Items))
for i := range valuesFilesRes.Items {
valueFilePath, err := filepath.Rel(appDir, valuesFilesRes.Items[i])
if err != nil {
return nil, err
}
appSpec.ValueFiles[i] = valueFilePath
}
return &RepoAppDetailsResponse{
Type: string(appSourceType),
Helm: &appSpec,

View File

@@ -422,8 +422,9 @@ func verifyGenerateManifests(ctx context.Context, repoRes *argoappv1.Repository,
Repo: &argoappv1.Repository{
Repo: spec.Source.RepoURL,
},
Revision: spec.Source.TargetRevision,
Path: spec.Source.Path,
Revision: spec.Source.TargetRevision,
Path: spec.Source.Path,
Namespace: spec.Destination.Namespace,
}
if repoRes != nil {
req.Repo.Username = repoRes.Username

View File

@@ -136,7 +136,7 @@ func (m *nativeGitClient) setCredentials() error {
func (m *nativeGitClient) Fetch() error {
var err error
log.Debugf("Fetching repo %s at %s", m.repoURL, m.root)
if _, err = m.runCmd("git", "fetch", "origin", "--tags"); err != nil {
if _, err = m.runCmd("git", "fetch", "origin", "--tags", "--force"); err != nil {
return err
}
// git fetch does not update the HEAD reference. The following command will update the local
@@ -192,7 +192,10 @@ func (m *nativeGitClient) Checkout(revision string) error {
if revision == "" || revision == "HEAD" {
revision = "origin/HEAD"
}
if _, err := m.runCmd("git", "checkout", revision); err != nil {
if _, err := m.runCmd("git", "checkout", "--force", revision); err != nil {
return err
}
if _, err := m.runCmd("git", "clean", "-fd"); err != nil {
return err
}
return nil

View File

@@ -18,9 +18,15 @@ import (
// Helm provides wrapper functionality around the `helm` command.
type Helm interface {
// Template returns a list of unstructured objects from a `helm template` command
Template(name string, valuesFiles []string, overrides []*argoappv1.ComponentParameter) ([]*unstructured.Unstructured, error)
Template(name, namespace string, valuesFiles []string, overrides []*argoappv1.ComponentParameter) ([]*unstructured.Unstructured, error)
// GetParameters returns a list of chart parameters taking into account values in provided YAML files.
GetParameters(valuesFiles []string) ([]*argoappv1.ComponentParameter, error)
// DependencyBuild runs `helm dependency build` to download a chart's dependencies
DependencyBuild() error
// SetHome sets the helm home location (default "~/.helm")
SetHome(path string)
// Init runs `helm init --client-only`
Init() error
}
// NewHelmApp create a new wrapper to run commands on the `helm` command-line tool.
@@ -30,27 +36,45 @@ func NewHelmApp(path string) Helm {
type helm struct {
path string
home string
}
func (h *helm) Template(name string, valuesFiles []string, overrides []*argoappv1.ComponentParameter) ([]*unstructured.Unstructured, error) {
func (h *helm) Template(name, namespace string, valuesFiles []string, overrides []*argoappv1.ComponentParameter) ([]*unstructured.Unstructured, error) {
args := []string{
"template", h.path, "--name", name,
"template", ".", "--name", name,
}
if namespace != "" {
args = append(args, "--namespace", namespace)
}
for _, valuesFile := range valuesFiles {
args = append(args, "-f", path.Join(h.path, valuesFile))
args = append(args, "-f", valuesFile)
}
for _, p := range overrides {
args = append(args, "--set", fmt.Sprintf("%s=%s", p.Name, p.Value))
}
out, err := helmCmd(args...)
out, err := h.helmCmd(args...)
if err != nil {
return nil, err
}
return kube.SplitYAML(out)
}
func (h *helm) DependencyBuild() error {
_, err := h.helmCmd("dependency", "build")
return err
}
func (h *helm) SetHome(home string) {
h.home = home
}
func (h *helm) Init() error {
_, err := h.helmCmd("init", "--client-only")
return err
}
func (h *helm) GetParameters(valuesFiles []string) ([]*argoappv1.ComponentParameter, error) {
out, err := helmCmd("inspect", "values", h.path)
out, err := h.helmCmd("inspect", "values", ".")
if err != nil {
return nil, err
}
@@ -82,8 +106,12 @@ func (h *helm) GetParameters(valuesFiles []string) ([]*argoappv1.ComponentParame
return params, nil
}
func helmCmd(args ...string) (string, error) {
func (h *helm) helmCmd(args ...string) (string, error) {
cmd := exec.Command("helm", args...)
cmd.Dir = h.path
if h.home != "" {
cmd.Env = append(cmd.Env, fmt.Sprintf("HELM_HOME=%s", h.home))
}
cmdStr := strings.Join(cmd.Args, " ")
log.Info(cmdStr)
outBytes, err := cmd.Output()

View File

@@ -1,6 +1,8 @@
package helm
import (
"io/ioutil"
"os"
"testing"
"github.com/stretchr/testify/assert"
@@ -32,7 +34,7 @@ func TestHelmTemplateParams(t *testing.T) {
Value: "1234",
},
}
objs, err := h.Template("test", nil, overrides)
objs, err := h.Template("test", "", nil, overrides)
assert.Nil(t, err)
assert.Equal(t, 5, len(objs))
@@ -50,7 +52,7 @@ func TestHelmTemplateParams(t *testing.T) {
func TestHelmTemplateValues(t *testing.T) {
h := NewHelmApp("./testdata/redis")
valuesFiles := []string{"values-production.yaml"}
objs, err := h.Template("test", valuesFiles, nil)
objs, err := h.Template("test", "", valuesFiles, nil)
assert.Nil(t, err)
assert.Equal(t, 8, len(objs))
@@ -84,3 +86,24 @@ func TestHelmGetParamsValueFiles(t *testing.T) {
assert.NotNil(t, slaveCountParam)
assert.Equal(t, slaveCountParam.Value, "3")
}
func TestHelmDependencyBuild(t *testing.T) {
clean := func() {
_ = os.RemoveAll("./testdata/wordpress/charts")
}
clean()
defer clean()
h := NewHelmApp("./testdata/wordpress")
helmHome, err := ioutil.TempDir("", "")
assert.NoError(t, err)
defer func() { _ = os.RemoveAll(helmHome) }()
h.SetHome(helmHome)
err = h.Init()
assert.NoError(t, err)
_, err = h.Template("wordpress", "", nil, nil)
assert.Error(t, err)
err = h.DependencyBuild()
assert.NoError(t, err)
_, err = h.Template("wordpress", "", nil, nil)
assert.NoError(t, err)
}

View File

@@ -0,0 +1,5 @@
.git
# OWNERS file for Kubernetes
OWNERS
# example production yaml
values-production.yaml

20
util/helm/testdata/wordpress/Chart.yaml vendored Normal file
View File

@@ -0,0 +1,20 @@
name: wordpress
version: 2.1.10
appVersion: 4.9.8
description: Web publishing platform for building blogs and websites.
icon: https://bitnami.com/assets/stacks/wordpress/img/wordpress-stack-220x234.png
keywords:
- wordpress
- cms
- blog
- http
- web
- application
- php
home: http://www.wordpress.com/
sources:
- https://github.com/bitnami/bitnami-docker-wordpress
maintainers:
- name: bitnami-bot
email: containers@bitnami.com
engine: gotpl

12
util/helm/testdata/wordpress/OWNERS vendored Normal file
View File

@@ -0,0 +1,12 @@
approvers:
- prydonius
- tompizmor
- sameersbn
- carrodher
- juan131
reviewers:
- prydonius
- tompizmor
- sameersbn
- carrodher
- juan131

232
util/helm/testdata/wordpress/README.md vendored Normal file
View File

@@ -0,0 +1,232 @@
# WordPress
[WordPress](https://wordpress.org/) is one of the most versatile open source content management systems on the market. A publishing platform for building blogs and websites.
## TL;DR;
```console
$ helm install stable/wordpress
```
## Introduction
This chart bootstraps a [WordPress](https://github.com/bitnami/bitnami-docker-wordpress) deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager.
It also packages the [Bitnami MariaDB chart](https://github.com/kubernetes/charts/tree/master/stable/mariadb) which is required for bootstrapping a MariaDB deployment for the database requirements of the WordPress application.
## Prerequisites
- Kubernetes 1.4+ with Beta APIs enabled
- PV provisioner support in the underlying infrastructure
## Installing the Chart
To install the chart with the release name `my-release`:
```console
$ helm install --name my-release stable/wordpress
```
The command deploys WordPress on the Kubernetes cluster in the default configuration. The [configuration](#configuration) section lists the parameters that can be configured during installation.
> **Tip**: List all releases using `helm list`
## Uninstalling the Chart
To uninstall/delete the `my-release` deployment:
```console
$ helm delete my-release
```
The command removes all the Kubernetes components associated with the chart and deletes the release.
## Configuration
The following table lists the configurable parameters of the WordPress chart and their default values.
| Parameter | Description | Default |
|----------------------------------|--------------------------------------------|---------------------------------------------------------|
| `image.registry` | WordPress image registry | `docker.io` |
| `image.repository` | WordPress image name | `bitnami/wordpress` |
| `image.tag` | WordPress image tag | `{VERSION}` |
| `image.pullPolicy` | Image pull policy | `Always` if `imageTag` is `latest`, else `IfNotPresent` |
| `image.pullSecrets` | Specify image pull secrets | `nil` |
| `wordpressUsername` | User of the application | `user` |
| `wordpressPassword` | Application password | _random 10 character long alphanumeric string_ |
| `wordpressEmail` | Admin email | `user@example.com` |
| `wordpressFirstName` | First name | `FirstName` |
| `wordpressLastName` | Last name | `LastName` |
| `wordpressBlogName` | Blog name | `User's Blog!` |
| `wordpressTablePrefix` | Table prefix | `wp_` |
| `allowEmptyPassword` | Allow DB blank passwords | `true` |
| `smtpHost` | SMTP host | `nil` |
| `smtpPort` | SMTP port | `nil` |
| `smtpUser` | SMTP user | `nil` |
| `smtpPassword` | SMTP password | `nil` |
| `smtpUsername` | User name for SMTP emails | `nil` |
| `smtpProtocol` | SMTP protocol [`tls`, `ssl`] | `nil` |
| `replicaCount` | Number of WordPress Pods to run | `1` |
| `mariadb.enabled` | Deploy MariaDB container(s) | `true` |
| `mariadb.rootUser.password` | MariaDB admin password | `nil` |
| `mariadb.db.name` | Database name to create | `bitnami_wordpress` |
| `mariadb.db.user` | Database user to create | `bn_wordpress` |
| `mariadb.db.password` | Password for the database | _random 10 character long alphanumeric string_ |
| `externalDatabase.host` | Host of the external database | `localhost` |
| `externalDatabase.user` | Existing username in the external db | `bn_wordpress` |
| `externalDatabase.password` | Password for the above username | `nil` |
| `externalDatabase.database` | Name of the existing database | `bitnami_wordpress` |
| `externalDatabase.port` | Database port number | `3306` |
| `serviceType` | Kubernetes Service type | `LoadBalancer` |
| `serviceExternalTrafficPolicy` | Enable client source IP preservation | `Cluster` |
| `nodePorts.http` | Kubernetes http node port | `""` |
| `nodePorts.https` | Kubernetes https node port | `""` |
| `healthcheckHttps` | Use https for liveliness and readiness | `false` |
| `ingress.enabled` | Enable ingress controller resource | `false` |
| `ingress.hosts[0].name` | Hostname to your WordPress installation | `wordpress.local` |
| `ingress.hosts[0].path` | Path within the url structure | `/` |
| `ingress.hosts[0].tls` | Utilize TLS backend in ingress | `false` |
| `ingress.hosts[0].tlsSecret` | TLS Secret (certificates) | `wordpress.local-tls-secret` |
| `ingress.hosts[0].annotations` | Annotations for this host's ingress record | `[]` |
| `ingress.secrets[0].name` | TLS Secret Name | `nil` |
| `ingress.secrets[0].certificate` | TLS Secret Certificate | `nil` |
| `ingress.secrets[0].key` | TLS Secret Key | `nil` |
| `persistence.enabled` | Enable persistence using PVC | `true` |
| `persistence.existingClaim` | Enable persistence using an existing PVC | `nil` |
| `persistence.storageClass` | PVC Storage Class | `nil` (uses alpha storage class annotation) |
| `persistence.accessMode` | PVC Access Mode | `ReadWriteOnce` |
| `persistence.size` | PVC Storage Request | `10Gi` |
| `nodeSelector` | Node labels for pod assignment | `{}` |
| `tolerations` | List of node taints to tolerate | `[]` |
| `affinity` | Map of node/pod affinities | `{}` |
The above parameters map to the env variables defined in [bitnami/wordpress](http://github.com/bitnami/bitnami-docker-wordpress). For more information please refer to the [bitnami/wordpress](http://github.com/bitnami/bitnami-docker-wordpress) image documentation.
Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example,
```console
$ helm install --name my-release \
--set wordpressUsername=admin,wordpressPassword=password,mariadb.mariadbRootPassword=secretpassword \
stable/wordpress
```
The above command sets the WordPress administrator account username and password to `admin` and `password` respectively. Additionally, it sets the MariaDB `root` user password to `secretpassword`.
Alternatively, a YAML file that specifies the values for the above parameters can be provided while installing the chart. For example,
```console
$ helm install --name my-release -f values.yaml stable/wordpress
```
> **Tip**: You can use the default [values.yaml](values.yaml)
## Production and horizontal scaling
The following repo contains the recommended production settings for wordpress capture in an alternative [values file](values-production.yaml). Please read carefully the comments in the values-production.yaml file to set up your environment appropriately.
To horizontally scale this chart, first download the [values-production.yaml](values-production.yaml) file to your local folder, then:
```console
$ helm install --name my-release -f ./values-production.yaml stable/wordpress
```
Note that [values-production.yaml](values-production.yaml) includes a replicaCount of 3, so there will be 3 WordPress pods. As a result, to use the /admin portal and to ensure you can scale wordpress you need to provide a ReadWriteMany PVC, if you don't have a provisioner for this type of storage, we recommend that you install the nfs provisioner and map it to a RWO volume.
```console
$ helm install stable/nfs-server-provisioner --set persistence.enabled=true,persistence.size=10Gi
$ helm install --name my-release -f values-production.yaml --set persistence.storageClass=nfs stable/wordpress
```
## Persistence
The [Bitnami WordPress](https://github.com/bitnami/bitnami-docker-wordpress) image stores the WordPress data and configurations at the `/bitnami` path of the container.
Persistent Volume Claims are used to keep the data across deployments. This is known to work in GCE, AWS, and minikube.
See the [Configuration](#configuration) section to configure the PVC or to disable persistence.
## Using an external database
Sometimes you may want to have Wordpress connect to an external database rather than installing one inside your cluster, e.g. to use a managed database service, or use run a single database server for all your applications. To do this, the chart allows you to specify credentials for an external database under the [`externalDatabase` parameter](#configuration). You should also disable the MariaDB installation with the `mariadb.enabled` option. For example:
```console
$ helm install stable/wordpress \
--set mariadb.enabled=false,externalDatabase.host=myexternalhost,externalDatabase.user=myuser,externalDatabase.password=mypassword,externalDatabase.database=mydatabase,externalDatabase.port=3306
```
Note also if you disable MariaDB per above you MUST supply values for the `externalDatabase` connection.
## Ingress
This chart provides support for ingress resources. If you have an
ingress controller installed on your cluster, such as [nginx-ingress](https://kubeapps.com/charts/stable/nginx-ingress)
or [traefik](https://kubeapps.com/charts/stable/traefik) you can utilize
the ingress controller to serve your WordPress application.
To enable ingress integration, please set `ingress.enabled` to `true`
### Hosts
Most likely you will only want to have one hostname that maps to this
WordPress installation, however, it is possible to have more than one
host. To facilitate this, the `ingress.hosts` object is an array.
For each item, please indicate a `name`, `tls`, `tlsSecret`, and any
`annotations` that you may want the ingress controller to know about.
Indicating TLS will cause WordPress to generate HTTPS URLs, and
WordPress will be connected to at port 443. The actual secret that
`tlsSecret` references do not have to be generated by this chart.
However, please note that if TLS is enabled, the ingress record will not
work until this secret exists.
For annotations, please see [this document](https://github.com/kubernetes/ingress-nginx/blob/master/docs/annotations.md).
Not all annotations are supported by all ingress controllers, but this
document does a good job of indicating which annotation is supported by
many popular ingress controllers.
### TLS Secrets
This chart will facilitate the creation of TLS secrets for use with the
ingress controller, however, this is not required. There are three
common use cases:
* helm generates/manages certificate secrets
* user generates/manages certificates separately
* an additional tool (like [kube-lego](https://kubeapps.com/charts/stable/kube-lego))
manages the secrets for the application
In the first two cases, one will need a certificate and a key. We would
expect them to look like this:
* certificate files should look like (and there can be more than one
certificate if there is a certificate chain)
```
-----BEGIN CERTIFICATE-----
MIID6TCCAtGgAwIBAgIJAIaCwivkeB5EMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV
...
jScrvkiBO65F46KioCL9h5tDvomdU1aqpI/CBzhvZn1c0ZTf87tGQR8NK7v7
-----END CERTIFICATE-----
```
* keys should look like:
```
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAvLYcyu8f3skuRyUgeeNpeDvYBCDcgq+LsWap6zbX5f8oLqp4
...
wrj2wDbCDCFmfqnSJ+dKI3vFLlEz44sAV8jX/kd4Y6ZTQhlLbYc=
-----END RSA PRIVATE KEY-----
````
If you are going to use Helm to manage the certificates, please copy
these values into the `certificate` and `key` values for a given
`ingress.secrets` entry.
If you are going are going to manage TLS secrets outside of Helm, please
know that you can create a TLS secret by doing the following:
```
kubectl create secret tls wordpress.local-tls --key /path/to/key.key --cert /path/to/cert.crt
```
Please see [this example](https://github.com/kubernetes/contrib/tree/master/ingress/controllers/nginx/examples/tls)
for more information.

View File

@@ -0,0 +1,6 @@
dependencies:
- name: mariadb
repository: https://kubernetes-charts.storage.googleapis.com/
version: 4.3.1
digest: sha256:82a0e5374376169d2ecf7d452c18a2ed93507f5d17c3393a1457f9ffad7e9b26
generated: 2018-08-02T22:07:51.905271776Z

View File

@@ -0,0 +1,7 @@
dependencies:
- name: mariadb
version: 4.x.x
repository: https://kubernetes-charts.storage.googleapis.com/
condition: mariadb.enabled
tags:
- wordpress-database

View File

@@ -0,0 +1,38 @@
1. Get the WordPress URL:
{{- if .Values.ingress.enabled }}
You should be able to access your new WordPress installation through
{{- range .Values.ingress.hosts }}
{{ if .tls }}https{{ else }}http{{ end }}://{{ .name }}/admin
{{- end }}
{{- else if contains "LoadBalancer" .Values.serviceType }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
Watch the status with: 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ template "fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo "WordPress URL: http://$SERVICE_IP/"
echo "WordPress Admin URL: http://$SERVICE_IP/admin"
{{- else if contains "ClusterIP" .Values.serviceType }}
echo "WordPress URL: http://127.0.0.1:8080/"
echo "WordPress Admin URL: http://127.0.0.1:8080/admin"
kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ template "fullname" . }} 8080:80
{{- else if contains "NodePort" .Values.serviceType }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "fullname" . }})
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo "WordPress URL: http://$NODE_IP:$NODE_PORT/"
echo "WordPress Admin URL: http://$NODE_IP:$NODE_PORT/admin"
{{- end }}
2. Login with the following credentials to see your blog
echo Username: {{ .Values.wordpressUsername }}
echo Password: $(kubectl get secret --namespace {{ .Release.Namespace }} {{ template "fullname" . }} -o jsonpath="{.data.wordpress-password}" | base64 --decode)

View File

@@ -0,0 +1,24 @@
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
*/}}
{{- define "fullname" -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
*/}}
{{- define "mariadb.fullname" -}}
{{- printf "%s-%s" .Release.Name "mariadb" | trunc 63 | trimSuffix "-" -}}
{{- end -}}

View File

@@ -0,0 +1,159 @@
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: {{ template "fullname" . }}
labels:
app: {{ template "fullname" . }}
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
spec:
replicas: {{ .Values.replicaCount }}
template:
metadata:
labels:
app: {{ template "fullname" . }}
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
spec:
{{- if .Values.image.pullSecrets }}
imagePullSecrets:
{{- range .Values.image.pullSecrets }}
- name: {{ . }}
{{- end}}
{{- end }}
containers:
- name: {{ template "fullname" . }}
image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy | quote }}
env:
- name: ALLOW_EMPTY_PASSWORD
{{- if .Values.allowEmptyPassword }}
value: "yes"
{{- else }}
value: "no"
{{- end }}
- name: MARIADB_HOST
{{- if .Values.mariadb.enabled }}
value: {{ template "mariadb.fullname" . }}
{{- else }}
value: {{ .Values.externalDatabase.host | quote }}
{{- end }}
- name: MARIADB_PORT_NUMBER
{{- if .Values.mariadb.enabled }}
value: "3306"
{{- else }}
value: {{ .Values.externalDatabase.port | quote }}
{{- end }}
- name: WORDPRESS_DATABASE_NAME
{{- if .Values.mariadb.enabled }}
value: {{ .Values.mariadb.db.name | quote }}
{{- else }}
value: {{ .Values.externalDatabase.database | quote }}
{{- end }}
- name: WORDPRESS_DATABASE_USER
{{- if .Values.mariadb.enabled }}
value: {{ .Values.mariadb.db.user | quote }}
{{- else }}
value: {{ .Values.externalDatabase.user | quote }}
{{- end }}
- name: WORDPRESS_DATABASE_PASSWORD
valueFrom:
secretKeyRef:
{{- if .Values.mariadb.enabled }}
name: {{ template "mariadb.fullname" . }}
key: mariadb-password
{{- else }}
name: {{ printf "%s-%s" .Release.Name "externaldb" }}
key: db-password
{{- end }}
- name: WORDPRESS_USERNAME
value: {{ .Values.wordpressUsername | quote }}
- name: WORDPRESS_PASSWORD
valueFrom:
secretKeyRef:
name: {{ template "fullname" . }}
key: wordpress-password
- name: WORDPRESS_EMAIL
value: {{ .Values.wordpressEmail | quote }}
- name: WORDPRESS_FIRST_NAME
value: {{ .Values.wordpressFirstName | quote }}
- name: WORDPRESS_LAST_NAME
value: {{ .Values.wordpressLastName | quote }}
- name: WORDPRESS_BLOG_NAME
value: {{ .Values.wordpressBlogName | quote }}
- name: WORDPRESS_TABLE_PREFIX
value: {{ .Values.wordpressTablePrefix | quote }}
- name: SMTP_HOST
value: {{ .Values.smtpHost | quote }}
- name: SMTP_PORT
value: {{ .Values.smtpPort | quote }}
- name: SMTP_USER
value: {{ .Values.smtpUser | quote }}
- name: SMTP_PASSWORD
valueFrom:
secretKeyRef:
name: {{ template "fullname" . }}
key: smtp-password
- name: SMTP_USERNAME
value: {{ .Values.smtpUsername | quote }}
- name: SMTP_PROTOCOL
value: {{ .Values.smtpProtocol | quote }}
ports:
- name: http
containerPort: 80
- name: https
containerPort: 443
livenessProbe:
httpGet:
path: /wp-login.php
{{- if not .Values.healthcheckHttps }}
port: http
{{- else }}
port: https
scheme: HTTPS
{{- end }}
{{ toYaml .Values.livenessProbe | indent 10 }}
readinessProbe:
httpGet:
path: /wp-login.php
{{- if not .Values.healthcheckHttps }}
port: http
{{- else }}
port: https
scheme: HTTPS
{{- end }}
{{ toYaml .Values.readinessProbe | indent 10 }}
volumeMounts:
- mountPath: /bitnami/apache
name: wordpress-data
subPath: apache
- mountPath: /bitnami/wordpress
name: wordpress-data
subPath: wordpress
- mountPath: /bitnami/php
name: wordpress-data
subPath: php
resources:
{{ toYaml .Values.resources | indent 10 }}
volumes:
- name: wordpress-data
{{- if .Values.persistence.enabled }}
persistentVolumeClaim:
claimName: {{ .Values.persistence.existingClaim | default (include "fullname" .) }}
{{- else }}
emptyDir: {}
{{ end }}
{{- if .Values.nodeSelector }}
nodeSelector:
{{ toYaml .Values.nodeSelector | indent 8 }}
{{- end -}}
{{- with .Values.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}

View File

@@ -0,0 +1,14 @@
{{- if not .Values.mariadb.enabled }}
apiVersion: v1
kind: Secret
metadata:
name: {{ printf "%s-%s" .Release.Name "externaldb" }}
labels:
app: {{ printf "%s-%s" .Release.Name "externaldb" }}
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
type: Opaque
data:
db-password: {{ .Values.externalDatabase.password | b64enc | quote }}
{{- end }}

View File

@@ -0,0 +1,36 @@
{{- if .Values.ingress.enabled }}
{{- range .Values.ingress.hosts }}
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: "{{- printf "%s-%s" .name $.Release.Name | trunc 63 | trimSuffix "-" -}}"
labels:
app: {{ template "fullname" $ }}
chart: "{{ $.Chart.Name }}-{{ $.Chart.Version }}"
release: "{{ $.Release.Name }}"
heritage: "{{ $.Release.Service }}"
annotations:
{{- if .tls }}
ingress.kubernetes.io/secure-backends: "true"
{{- end }}
{{- range $key, $value := .annotations }}
{{ $key }}: {{ $value | quote }}
{{- end }}
spec:
rules:
- host: {{ .name }}
http:
paths:
- path: {{ default "/" .path }}
backend:
serviceName: {{ template "fullname" $ }}
servicePort: 80
{{- if .tls }}
tls:
- hosts:
- {{ .name }}
secretName: {{ .tlsSecret }}
{{- end }}
---
{{- end }}
{{- end }}

View File

@@ -0,0 +1,24 @@
{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) }}
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: {{ template "fullname" . }}
labels:
app: {{ template "fullname" . }}
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
spec:
accessModes:
- {{ .Values.persistence.accessMode | quote }}
resources:
requests:
storage: {{ .Values.persistence.size | quote }}
{{- if .Values.persistence.storageClass }}
{{- if (eq "-" .Values.persistence.storageClass) }}
storageClassName: ""
{{- else }}
storageClassName: "{{ .Values.persistence.storageClass }}"
{{- end }}
{{- end }}
{{- end -}}

View File

@@ -0,0 +1,17 @@
apiVersion: v1
kind: Secret
metadata:
name: {{ template "fullname" . }}
labels:
app: {{ template "fullname" . }}
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
type: Opaque
data:
{{ if .Values.wordpressPassword }}
wordpress-password: {{ default "" .Values.wordpressPassword | b64enc | quote }}
{{ else }}
wordpress-password: {{ randAlphaNum 10 | b64enc | quote }}
{{ end }}
smtp-password: {{ default "" .Values.smtpPassword | b64enc | quote }}

View File

@@ -0,0 +1,29 @@
apiVersion: v1
kind: Service
metadata:
name: {{ template "fullname" . }}
labels:
app: {{ template "fullname" . }}
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
spec:
type: {{ .Values.serviceType }}
{{- if (or (eq .Values.serviceType "LoadBalancer") (eq .Values.serviceType "NodePort")) }}
externalTrafficPolicy: {{ .Values.serviceExternalTrafficPolicy | quote }}
{{- end }}
ports:
- name: http
port: 80
targetPort: http
{{- if (and (eq .Values.serviceType "NodePort") (not (empty .Values.nodePorts.http)))}}
nodePort: {{ .Values.nodePorts.http }}
{{- end }}
- name: https
port: 443
targetPort: https
{{- if (and (eq .Values.serviceType "NodePort") (not (empty .Values.nodePorts.https)))}}
nodePort: {{ .Values.nodePorts.https }}
{{- end }}
selector:
app: {{ template "fullname" . }}

View File

@@ -0,0 +1,29 @@
{{- if .Values.mariadb.enabled }}
apiVersion: v1
kind: Pod
metadata:
name: "{{ .Release.Name }}-credentials-test"
annotations:
"helm.sh/hook": test-success
spec:
containers:
- name: {{ .Release.Name }}-credentials-test
image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy | quote }}
env:
- name: MARIADB_HOST
value: {{ template "mariadb.fullname" . }}
- name: MARIADB_PORT
value: "3306"
- name: WORDPRESS_DATABASE_NAME
value: {{ default "" .Values.mariadb.db.name | quote }}
- name: WORDPRESS_DATABASE_USER
value: {{ default "" .Values.mariadb.db.user | quote }}
- name: WORDPRESS_DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: {{ template "mariadb.fullname" . }}
key: mariadb-password
command: ["sh", "-c", "mysql --host=$MARIADB_HOST --port=$MARIADB_PORT --user=$WORDPRESS_DATABASE_USER --password=$WORDPRESS_DATABASE_PASSWORD"]
restartPolicy: Never
{{- end }}

View File

@@ -0,0 +1,18 @@
{{- if .Values.ingress.enabled }}
{{- range .Values.ingress.secrets }}
apiVersion: v1
kind: Secret
metadata:
name: {{ .name }}
labels:
app: {{ template "fullname" $ }}
chart: "{{ $.Chart.Name }}-{{ $.Chart.Version }}"
release: "{{ $.Release.Name }}"
heritage: "{{ $.Release.Service }}"
type: kubernetes.io/tls
data:
tls.crt: {{ .certificate | b64enc }}
tls.key: {{ .key | b64enc }}
---
{{- end }}
{{- end }}

View File

@@ -0,0 +1,256 @@
## Bitnami WordPress image version
## ref: https://hub.docker.com/r/bitnami/wordpress/tags/
##
image:
registry: docker.io
repository: bitnami/wordpress
tag: 4.9.8-debian-9
pullPolicy: IfNotPresent
## Optionally specify an array of imagePullSecrets.
## Secrets must be manually created in the namespace.
## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
##
# pullSecrets:
# - myRegistrKeySecretName
## User of the application
## ref: https://github.com/bitnami/bitnami-docker-wordpress#environment-variables
##
wordpressUsername: user
## Application password
## Defaults to a random 10-character alphanumeric string if not set
## ref: https://github.com/bitnami/bitnami-docker-wordpress#environment-variables
##
# wordpressPassword:
## Admin email
## ref: https://github.com/bitnami/bitnami-docker-wordpress#environment-variables
##
wordpressEmail: user@example.com
## First name
## ref: https://github.com/bitnami/bitnami-docker-wordpress#environment-variables
##
wordpressFirstName: FirstName
## Last name
## ref: https://github.com/bitnami/bitnami-docker-wordpress#environment-variables
##
wordpressLastName: LastName
## Blog name
## ref: https://github.com/bitnami/bitnami-docker-wordpress#environment-variables
##
wordpressBlogName: User's Blog!
## Table prefix
## ref: https://github.com/bitnami/bitnami-docker-wordpress#environment-variables
##
wordpressTablePrefix: wp_
## Set to `yes` to allow the container to be started with blank passwords
## ref: https://github.com/bitnami/bitnami-docker-wordpress#environment-variables
allowEmptyPassword: "yes"
## SMTP mail delivery configuration
## ref: https://github.com/bitnami/bitnami-docker-wordpress/#smtp-configuration
##
# smtpHost:
# smtpPort:
# smtpUser:
# smtpPassword:
# smtpUsername:
# smtpProtocol:
replicaCount: 3
externalDatabase:
## All of these values are only used when mariadb.enabled is set to false
## Database host
host: localhost
## non-root Username for Wordpress Database
user: bn_wordpress
## Database password
password: ""
## Database name
database: bitnami_wordpress
## Database port number
port: 3306
##
## MariaDB chart configuration
##
mariadb:
## Whether to deploy a mariadb server to satisfy the applications database requirements. To use an external database set this to false and configure the externalDatabase parameters
enabled: true
## Disable MariaDB replication
replication:
enabled: false
## Create a database and a database user
## ref: https://github.com/bitnami/bitnami-docker-mariadb/blob/master/README.md#creating-a-database-user-on-first-run
##
db:
name: bitnami_wordpress
user: bn_wordpress
## If the password is not specified, mariadb will generates a random password
##
# password:
## MariaDB admin password
## ref: https://github.com/bitnami/bitnami-docker-mariadb/blob/master/README.md#setting-the-root-password-on-first-run
##
# rootUser:
# password:
## Enable persistence using Persistent Volume Claims
## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/
##
master:
persistence:
enabled: true
## mariadb data Persistent Volume Storage Class
## If defined, storageClassName: <storageClass>
## If set to "-", storageClassName: "", which disables dynamic provisioning
## If undefined (the default) or set to null, no storageClassName spec is
## set, choosing the default provisioner. (gp2 on AWS, standard on
## GKE, AWS & OpenStack)
##
# storageClass: "-"
accessMode: ReadWriteOnce
size: 8Gi
## Kubernetes configuration
## For minikube, set this to NodePort, elsewhere use LoadBalancer or ClusterIP
##
serviceType: ClusterIP
##
## serviceType: NodePort
## nodePorts:
## http: <to set explicitly, choose port between 30000-32767>
## https: <to set explicitly, choose port between 30000-32767>
nodePorts:
http: ""
https: ""
## Enable client source IP preservation
## ref http://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip
##
serviceExternalTrafficPolicy: Local
## Allow health checks to be pointed at the https port
healthcheckHttps: false
## Configure extra options for liveness and readiness probes
## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes)
livenessProbe:
initialDelaySeconds: 120
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 6
successThreshold: 1
readinessProbe:
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 6
successThreshold: 1
## Configure the ingress resource that allows you to access the
## Wordpress installation. Set up the URL
## ref: http://kubernetes.io/docs/user-guide/ingress/
##
ingress:
## Set to true to enable ingress record generation
enabled: true
## The list of hostnames to be covered with this ingress record.
## Most likely this will be just one host, but in the event more hosts are needed, this is an array
## Please make sure to change the name and tlsSecret to your own settings
hosts:
- name: wordpress.local
## Set this to true in order to enable TLS on the ingress record
## A side effect of this will be that the backend wordpress service will be connected at port 443
tls: true
## If TLS is set to true, you must declare what secret will store the key/certificate for TLS
tlsSecret: wordpress.local-tls
## Ingress annotations done as key:value pairs
## If you're using kube-lego, you will want to add:
## kubernetes.io/tls-acme: true
##
## For a full list of possible ingress annotations, please see
## ref: https://github.com/kubernetes/ingress-nginx/blob/master/docs/annotations.md
##
## If tls is set to true, annotation ingress.kubernetes.io/secure-backends: "true" will automatically be set
annotations:
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: true
secrets:
## If you're providing your own certificates, please use this to add the certificates as secrets
## key and certificate should start with -----BEGIN CERTIFICATE----- or
## -----BEGIN RSA PRIVATE KEY-----
##
## name should line up with a tlsSecret set further up
## If you're using kube-lego, this is unneeded, as it will create the secret for you if it is not set
##
## It is also possible to create and manage the certificates outside of this helm chart
## Please see README.md for more information
# - name: wordpress.local-tls
# key:
# certificate:
## Enable persistence using Persistent Volume Claims
## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/
##
persistence:
enabled: true
## wordpress data Persistent Volume Storage Class
## If defined, storageClassName: <storageClass>
## If set to "-", storageClassName: "", which disables dynamic provisioning
## If undefined (the default) or set to null, no storageClassName spec is
## set, choosing the default provisioner. (gp2 on AWS, standard on
## GKE, AWS & OpenStack)
##
# storageClass: "-"
##
## If you want to reuse an existing claim, you can pass the name of the PVC using
## the existingClaim variable
# existingClaim: your-claim
##
## To use the /admin portal and to ensure you can scale wordpress you need to provide a
## ReadWriteMany PVC, if you dont have a provisioner for this type of storage
## We recommend that you install the nfs provisioner and map it to a RWO volume
## helm install stable/nfs-server-provisioner --set persistence.enabled=true,persistence.size=10Gi
accessMode: ReadWriteMany
size: 10Gi
## Configure resource requests and limits
## ref: http://kubernetes.io/docs/user-guide/compute-resources/
##
resources:
requests:
memory: 512Mi
cpu: 300m
## Node labels for pod assignment
## Ref: https://kubernetes.io/docs/user-guide/node-selection/
##
nodeSelector: {}
## Tolerations for pod assignment
## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
##
tolerations: []
## Affinity for pod assignment
## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
##
affinity: {}

254
util/helm/testdata/wordpress/values.yaml vendored Normal file
View File

@@ -0,0 +1,254 @@
## Bitnami WordPress image version
## ref: https://hub.docker.com/r/bitnami/wordpress/tags/
##
image:
registry: docker.io
repository: bitnami/wordpress
tag: 4.9.8-debian-9
## Specify a imagePullPolicy
## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent'
## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images
##
pullPolicy: IfNotPresent
## Optionally specify an array of imagePullSecrets.
## Secrets must be manually created in the namespace.
## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
##
# pullSecrets:
# - myRegistrKeySecretName
## User of the application
## ref: https://github.com/bitnami/bitnami-docker-wordpress#environment-variables
##
wordpressUsername: user
## Application password
## Defaults to a random 10-character alphanumeric string if not set
## ref: https://github.com/bitnami/bitnami-docker-wordpress#environment-variables
##
# wordpressPassword:
## Admin email
## ref: https://github.com/bitnami/bitnami-docker-wordpress#environment-variables
##
wordpressEmail: user@example.com
## First name
## ref: https://github.com/bitnami/bitnami-docker-wordpress#environment-variables
##
wordpressFirstName: FirstName
## Last name
## ref: https://github.com/bitnami/bitnami-docker-wordpress#environment-variables
##
wordpressLastName: LastName
## Blog name
## ref: https://github.com/bitnami/bitnami-docker-wordpress#environment-variables
##
wordpressBlogName: User's Blog!
## Table prefix
## ref: https://github.com/bitnami/bitnami-docker-wordpress#environment-variables
##
wordpressTablePrefix: wp_
## Set to `false` to allow the container to be started with blank passwords
## ref: https://github.com/bitnami/bitnami-docker-wordpress#environment-variables
allowEmptyPassword: true
## SMTP mail delivery configuration
## ref: https://github.com/bitnami/bitnami-docker-wordpress/#smtp-configuration
##
# smtpHost:
# smtpPort:
# smtpUser:
# smtpPassword:
# smtpUsername:
# smtpProtocol:
replicaCount: 1
externalDatabase:
## All of these values are only used when mariadb.enabled is set to false
## Database host
host: localhost
## non-root Username for Wordpress Database
user: bn_wordpress
## Database password
password: ""
## Database name
database: bitnami_wordpress
## Database port number
port: 3306
##
## MariaDB chart configuration
##
mariadb:
## Whether to deploy a mariadb server to satisfy the applications database requirements. To use an external database set this to false and configure the externalDatabase parameters
enabled: true
## Disable MariaDB replication
replication:
enabled: false
## Create a database and a database user
## ref: https://github.com/bitnami/bitnami-docker-mariadb/blob/master/README.md#creating-a-database-user-on-first-run
##
db:
name: bitnami_wordpress
user: bn_wordpress
## If the password is not specified, mariadb will generates a random password
##
# password:
## MariaDB admin password
## ref: https://github.com/bitnami/bitnami-docker-mariadb/blob/master/README.md#setting-the-root-password-on-first-run
##
# rootUser:
# password:
## Enable persistence using Persistent Volume Claims
## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/
##
master:
persistence:
enabled: true
## mariadb data Persistent Volume Storage Class
## If defined, storageClassName: <storageClass>
## If set to "-", storageClassName: "", which disables dynamic provisioning
## If undefined (the default) or set to null, no storageClassName spec is
## set, choosing the default provisioner. (gp2 on AWS, standard on
## GKE, AWS & OpenStack)
##
# storageClass: "-"
accessMode: ReadWriteOnce
size: 8Gi
## Kubernetes configuration
## For minikube, set this to NodePort, elsewhere use LoadBalancer or ClusterIP
##
serviceType: LoadBalancer
##
## serviceType: NodePort
## nodePorts:
## http: <to set explicitly, choose port between 30000-32767>
## https: <to set explicitly, choose port between 30000-32767>
nodePorts:
http: ""
https: ""
## Enable client source IP preservation
## ref http://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip
##
serviceExternalTrafficPolicy: Cluster
## Allow health checks to be pointed at the https port
healthcheckHttps: false
## Configure extra options for liveness and readiness probes
## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes)
livenessProbe:
initialDelaySeconds: 120
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 6
successThreshold: 1
readinessProbe:
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 6
successThreshold: 1
## Configure the ingress resource that allows you to access the
## Wordpress installation. Set up the URL
## ref: http://kubernetes.io/docs/user-guide/ingress/
##
ingress:
## Set to true to enable ingress record generation
enabled: false
## The list of hostnames to be covered with this ingress record.
## Most likely this will be just one host, but in the event more hosts are needed, this is an array
hosts:
- name: wordpress.local
## Set this to true in order to enable TLS on the ingress record
## A side effect of this will be that the backend wordpress service will be connected at port 443
tls: false
## If TLS is set to true, you must declare what secret will store the key/certificate for TLS
tlsSecret: wordpress.local-tls
## Ingress annotations done as key:value pairs
## If you're using kube-lego, you will want to add:
## kubernetes.io/tls-acme: true
##
## For a full list of possible ingress annotations, please see
## ref: https://github.com/kubernetes/ingress-nginx/blob/master/docs/annotations.md
##
## If tls is set to true, annotation ingress.kubernetes.io/secure-backends: "true" will automatically be set
annotations:
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: true
secrets:
## If you're providing your own certificates, please use this to add the certificates as secrets
## key and certificate should start with -----BEGIN CERTIFICATE----- or
## -----BEGIN RSA PRIVATE KEY-----
##
## name should line up with a tlsSecret set further up
## If you're using kube-lego, this is unneeded, as it will create the secret for you if it is not set
##
## It is also possible to create and manage the certificates outside of this helm chart
## Please see README.md for more information
# - name: wordpress.local-tls
# key:
# certificate:
## Enable persistence using Persistent Volume Claims
## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/
##
persistence:
enabled: true
## wordpress data Persistent Volume Storage Class
## If defined, storageClassName: <storageClass>
## If set to "-", storageClassName: "", which disables dynamic provisioning
## If undefined (the default) or set to null, no storageClassName spec is
## set, choosing the default provisioner. (gp2 on AWS, standard on
## GKE, AWS & OpenStack)
##
# storageClass: "-"
##
## If you want to reuse an existing claim, you can pass the name of the PVC using
## the existingClaim variable
# existingClaim: your-claim
accessMode: ReadWriteOnce
size: 10Gi
## Configure resource requests and limits
## ref: http://kubernetes.io/docs/user-guide/compute-resources/
##
resources:
requests:
memory: 512Mi
cpu: 300m
## Node labels for pod assignment
## Ref: https://kubernetes.io/docs/user-guide/node-selection/
##
nodeSelector: {}
## Tolerations for pod assignment
## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
##
tolerations: []
## Affinity for pod assignment
## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
##
affinity: {}

View File

@@ -323,12 +323,11 @@ func GetResourcesWithLabel(config *rest.Config, namespace string, labelName stri
var asyncErr error
var result []*unstructured.Unstructured
var wg sync.WaitGroup
var lock sync.Mutex
wg.Add(len(resourceInterfaces))
for i := range resourceInterfaces {
client := resourceInterfaces[i]
go func() {
for _, c := range resourceInterfaces {
go func(client dynamic.ResourceInterface) {
defer wg.Done()
list, err := client.List(metav1.ListOptions{
LabelSelector: fmt.Sprintf("%s=%s", labelName, labelValue),
@@ -343,11 +342,13 @@ func GetResourcesWithLabel(config *rest.Config, namespace string, labelName stri
labels := item.GetLabels()
if labels != nil {
if value, ok := labels[labelName]; ok && value == labelValue {
lock.Lock()
result = append(result, &item)
lock.Unlock()
}
}
}
}()
}(c)
}
wg.Wait()
return result, asyncErr
@@ -365,10 +366,11 @@ func DeleteResourceWithLabel(config *rest.Config, namespace string, labelName st
return err
}
var resourceInterfaces []struct {
type resClient struct {
dynamic.ResourceInterface
bool
deleteCollectionSupported bool
}
var resourceInterfaces []resClient
for _, apiResourcesList := range resources {
for i := range apiResourcesList.APIResources {
@@ -388,10 +390,10 @@ func DeleteResourceWithLabel(config *rest.Config, namespace string, labelName st
}
if deleteCollectionSupported || deleteSupported {
resourceInterfaces = append(resourceInterfaces, struct {
dynamic.ResourceInterface
bool
}{dclient.Resource(&apiResource, namespace), deleteCollectionSupported})
resourceInterfaces = append(resourceInterfaces, resClient{
dclient.Resource(&apiResource, namespace),
deleteCollectionSupported,
})
}
}
}
@@ -402,13 +404,10 @@ func DeleteResourceWithLabel(config *rest.Config, namespace string, labelName st
var wg sync.WaitGroup
wg.Add(len(resourceInterfaces))
for i := range resourceInterfaces {
client := resourceInterfaces[i].ResourceInterface
deleteCollectionSupported := resourceInterfaces[i].bool
go func() {
for _, c := range resourceInterfaces {
go func(client resClient) {
defer wg.Done()
if deleteCollectionSupported {
if client.deleteCollectionSupported {
err = client.DeleteCollection(&metav1.DeleteOptions{
PropagationPolicy: &propagationPolicy,
}, metav1.ListOptions{LabelSelector: fmt.Sprintf("%s=%s", labelName, labelValue)})
@@ -437,7 +436,7 @@ func DeleteResourceWithLabel(config *rest.Config, namespace string, labelName st
}
}
}
}()
}(c)
}
wg.Wait()
return asyncErr