/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License.  You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package trait

import (
	"strconv"

	appsv1 "k8s.io/api/apps/v1"

	servingv1 "knative.dev/serving/pkg/apis/serving/v1"

	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
)

// The Istio trait allows to configure properties related to the Istio service mesh,
// such as sidecar injection and outbound IP ranges.
//
// +camel-k:trait=istio
type istioTrait struct {
	BaseTrait `property:",squash"`
	// Configures a (comma-separated) list of CIDR subnets that should not be intercepted by the Istio proxy (`10.0.0.0/8,172.16.0.0/12,192.168.0.0/16` by default).
	Allow string `property:"allow"`
	// Forces the value for labels `sidecar.istio.io/inject`. By default the label is set to `true` on deployment and not set on Knative Service.
	Inject *bool `property:"inject"`
}

const (
	istioSidecarInjectAnnotation    = "sidecar.istio.io/inject"
	istioOutboundIPRangesAnnotation = "traffic.sidecar.istio.io/includeOutboundIPRanges"
)

func newIstioTrait() Trait {
	return &istioTrait{
		BaseTrait: NewBaseTrait("istio", 2300),
		Allow:     "10.0.0.0/8,172.16.0.0/12,192.168.0.0/16",
	}
}

func (t *istioTrait) Configure(e *Environment) (bool, error) {
	if t.Enabled != nil && *t.Enabled {
		return e.IntegrationInPhase(v1.IntegrationPhaseDeploying, v1.IntegrationPhaseRunning), nil
	}

	return false, nil
}

func (t *istioTrait) Apply(e *Environment) error {
	if t.Allow != "" {
		e.Resources.VisitDeployment(func(d *appsv1.Deployment) {
			d.Spec.Template.Annotations = t.injectIstioAnnotation(d.Spec.Template.Annotations, true)
		})
		e.Resources.VisitKnativeConfigurationSpec(func(cs *servingv1.ConfigurationSpec) {
			cs.Template.Annotations = t.injectIstioAnnotation(cs.Template.Annotations, false)
		})
	}
	return nil
}

func (t *istioTrait) injectIstioAnnotation(annotations map[string]string, includeInject bool) map[string]string {
	if annotations == nil {
		annotations = make(map[string]string)
	}
	annotations[istioOutboundIPRangesAnnotation] = t.Allow
	if includeInject {
		annotations[istioSidecarInjectAnnotation] = True
	}
	if t.Inject != nil {
		annotations[istioSidecarInjectAnnotation] = strconv.FormatBool(*t.Inject)
	}
	return annotations
}
