Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
5a436ca
updated kind with apisplitter
tthebst Jun 29, 2020
a15751a
added apisplitter useconfig
tthebst Jun 29, 2020
076f817
apisplit yaml example
tthebst Jun 29, 2020
71ed5a4
created apisplitter resource barebones
tthebst Jun 29, 2020
96fb362
added apisplitter validations
tthebst Jun 29, 2020
3de9271
migrated logic to overloading api config
tthebst Jun 30, 2020
1f2b225
basic post spec validation done
tthebst Jul 2, 2020
2a66b27
adding splitting logic to virtual service
tthebst Jul 2, 2020
bd5159a
working splitter update
tthebst Jul 3, 2020
840ac1b
api gateway support for trafficsplit
tthebst Jul 3, 2020
bee84df
delete useless stuff for trafficsplitter
tthebst Jul 3, 2020
a0dc90f
merge master into branch && resolv conflict
tthebst Jul 3, 2020
e32770d
add get command for trafficsplitter
tthebst Jul 4, 2020
7f3203f
add trafficsplit table and get all deployments
tthebst Jul 4, 2020
6c8bda0
cleanup and comments
tthebst Jul 6, 2020
f61d9a5
cli update to get status of trafficsplitter
tthebst Jul 6, 2020
d2ece7d
fix test error
tthebst Jul 6, 2020
b7f0ef6
fix comparison on virtual services
tthebst Jul 6, 2020
c8b3aa3
new traffic split get table
tthebst Jul 6, 2020
42dcf9b
add new get all table for trafficsplitter
tthebst Jul 6, 2020
e428df3
add endpoint duplication check
tthebst Jul 6, 2020
3aa441e
add check if api used by apisplitter
tthebst Jul 8, 2020
528e143
fix bug virtual service naming and remove print statements
tthebst Jul 8, 2020
764a22e
apisplitter not supported on local check
tthebst Jul 8, 2020
caba5a9
imporve cli output format
tthebst Jul 8, 2020
b41d640
fixes and formatting
tthebst Jul 8, 2020
699534f
allow 0 weight trafficsplitter
tthebst Jul 8, 2020
fbc6f1d
Merge branch 'master' into trafficsplit
tthebst Jul 9, 2020
982e2c6
update cli trafficsplit get table
tthebst Jul 11, 2020
6effac9
improve error messages
tthebst Jul 11, 2020
80ce487
Merge branch 'trafficsplit' of github.com:cortexlabs/cortex into traf…
tthebst Jul 11, 2020
4180e84
Merge branch 'master' into trafficsplit
vishalbollu Jul 14, 2020
49a909d
Update apisplit.yaml
vishalbollu Jul 14, 2020
d22e9d8
rewrite virtual service destination definition
tthebst Jul 14, 2020
3bc5ab4
code review improvments
tthebst Jul 15, 2020
cdbeb86
review improvements
tthebst Jul 16, 2020
dc9c7bb
code review improvements
tthebst Jul 22, 2020
5e2bc69
remove apisplit example
tthebst Jul 22, 2020
d784c5a
correct table for cortex get
tthebst Jul 22, 2020
493c1d1
remove print statements
tthebst Jul 22, 2020
7dcf104
code review improvements
tthebst Jul 26, 2020
b414dda
add API uniqueness check && review improvements
tthebst Jul 28, 2020
3f0afe5
Nits
vishalbollu Jul 29, 2020
b8b8ba8
Only allow logs command for Sync APIs
vishalbollu Jul 29, 2020
da67d06
Merge branch 'master' into trafficsplit
vishalbollu Jul 29, 2020
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
working splitter update
  • Loading branch information
tthebst committed Jul 3, 2020
commit bd5159ad5ac8d9e79965ca1edf3cc7c385fd06f5
84 changes: 35 additions & 49 deletions pkg/operator/resources/apisplitter/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package apisplitter
import (
"fmt"
"path/filepath"
"reflect"
"strings"

"github.com/cortexlabs/cortex/pkg/lib/cron"
Expand All @@ -39,58 +40,43 @@ import (
var _autoscalerCrons = make(map[string]cron.Cron) // apiName -> cron

func UpdateAPI(apiConfig *userconfig.API, projectID string, force bool) (*spec.API, string, error) {
prevDeployment, prevService, prevVirtualService, err := getK8sResources(apiConfig)
prevVirtualService, err := getK8sResources(apiConfig)
if err != nil {
return nil, "", err
}
fmt.Println("LOOOADBALANNNNCER")
fmt.Println(operator.APILoadBalancerURL())
api := spec.GetAPISpec(apiConfig, projectID, "")

deploymentID := k8s.RandomName()
if prevDeployment != nil && prevDeployment.Labels["deploymentID"] != "" {
deploymentID = prevDeployment.Labels["deploymentID"]
}

api := spec.GetAPISpec(apiConfig, projectID, deploymentID)

if prevDeployment == nil {
if prevVirtualService == nil {
if err := config.AWS.UploadMsgpackToS3(api, config.Cluster.Bucket, api.Key); err != nil {
return nil, "", errors.Wrap(err, "upload api spec")
}
if err := applyK8sResources(api, prevDeployment, prevService, prevVirtualService); err != nil {
if err := applyK8sResources(api, prevVirtualService); err != nil {
go deleteK8sResources(api.Name)
return nil, "", err
}

return api, fmt.Sprintf("creating %s", api.Name), nil
}
services, weight := getServicesWeightsTrafficSplitter(api)
if err != nil {
return nil, "", err
}

if !areAPIsEqual(prevDeployment, deploymentSpec(api, prevDeployment)) {
isUpdating, err := isAPIUpdating(prevDeployment)
if err != nil {
return nil, "", err
}
if isUpdating && !force {
return nil, "", ErrorAPIUpdating(api.Name)
}
if !areVirtualServiceEqual(prevVirtualService, virtualServiceSpec(api, services, weight)) {
if err := config.AWS.UploadMsgpackToS3(api, config.Cluster.Bucket, api.Key); err != nil {
return nil, "", errors.Wrap(err, "upload api spec")
}
if err := applyK8sResources(api, prevDeployment, prevService, prevVirtualService); err != nil {
return nil, "", err
}
if err := operator.UpdateAPIGatewayK8s(prevVirtualService, api); err != nil {
if err := applyK8sResources(api, prevVirtualService); err != nil {
return nil, "", err
}
// if err := operator.UpdateAPIGatewayK8s(prevVirtualService, api); err != nil {
// return nil, "", err
// }
return api, fmt.Sprintf("updating %s", api.Name), nil
}

// deployment didn't change
isUpdating, err := isAPIUpdating(prevDeployment)
if err != nil {
return nil, "", err
}
if isUpdating {
return api, fmt.Sprintf("%s is already updating", api.Name), nil
}
return api, fmt.Sprintf("%s is up to date", api.Name), nil
}

Expand Down Expand Up @@ -136,7 +122,7 @@ func RefreshAPI(apiName string, force bool) (string, error) {

func DeleteAPI(apiName string, keepCache bool) error {
// best effort deletion, so don't handle error yet
virtualService, vsErr := config.K8s.GetVirtualService(operator.K8sName(apiName))
virtualService, vsErr := config.K8s.GetVirtualService(apiName)

err := parallel.RunFirstErr(
func() error {
Expand Down Expand Up @@ -205,15 +191,15 @@ func getK8sResources(apiConfig *userconfig.API) (*istioclientnetworking.VirtualS
// },
func() error {
var err error
virtualService, err = config.K8s.GetVirtualService(operator.K8sName(apiConfig.Name))
virtualService, err = config.K8s.GetVirtualService(apiConfig.Name)
return err
},
)

return virtualService, err
}

func applyK8sResources(api *spec.API, prevDeployment *kapps.Deployment, prevService *kcore.Service, prevVirtualService *istioclientnetworking.VirtualService) error {
func applyK8sResources(api *spec.API, prevVirtualService *istioclientnetworking.VirtualService) error {
return parallel.RunFirstErr(
// func() error {
// return applyK8sDeployment(api, prevDeployment)
Expand Down Expand Up @@ -287,15 +273,9 @@ func applyK8sService(api *spec.API, prevService *kcore.Service) error {
}

func applyK8sVirtualService(trafficsplitter *spec.API, prevVirtualService *istioclientnetworking.VirtualService) error {
services := []string{}
weights := []int32{}
for _, api := range trafficsplitter.APIs {
service, _ := config.K8s.GetService("api-" + api.Name)
services = append(services, service.GetName())
weights = append(weights, int32(api.Weight))
}
fmt.Println(services)
fmt.Println(weights)

services, weights := getServicesWeightsTrafficSplitter(trafficsplitter)

newVirtualService := virtualServiceSpec(trafficsplitter, services, weights)

if prevVirtualService == nil {
Expand All @@ -307,6 +287,17 @@ func applyK8sVirtualService(trafficsplitter *spec.API, prevVirtualService *istio
return err
}

func getServicesWeightsTrafficSplitter(trafficsplitter *spec.API) ([]string, []int32) {
services := []string{}
weights := []int32{}
for _, api := range trafficsplitter.APIs {
services = append(services, "api-"+api.Name)
weights = append(weights, int32(api.Weight))
}
return services, weights

}

func deleteK8sResources(apiName string) error {
return parallel.RunFirstErr(
func() error {
Expand Down Expand Up @@ -371,13 +362,8 @@ func isPodSpecLatest(deployment *kapps.Deployment, pod *kcore.Pod) bool {
deployment.Spec.Template.Labels["deploymentID"] == pod.Labels["deploymentID"]
}

func areAPIsEqual(d1, d2 *kapps.Deployment) bool {
return k8s.PodComputesEqual(&d1.Spec.Template.Spec, &d2.Spec.Template.Spec) &&
k8s.DeploymentStrategiesMatch(d1.Spec.Strategy, d2.Spec.Strategy) &&
d1.Labels["apiName"] == d2.Labels["apiName"] &&
d1.Labels["apiID"] == d2.Labels["apiID"] &&
d1.Labels["deploymentID"] == d2.Labels["deploymentID"] &&
doCortexAnnotationsMatch(d1, d2)
func areVirtualServiceEqual(vs1, vs2 *istioclientnetworking.VirtualService) bool {
return reflect.DeepEqual(vs1, vs2)
}

func doCortexAnnotationsMatch(obj1, obj2 kmeta.Object) bool {
Expand Down
1 change: 0 additions & 1 deletion pkg/operator/resources/apisplitter/k8s_specs.go
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,6 @@ func serviceSpec(api *spec.API) *kcore.Service {
}

func virtualServiceSpec(trafficsplitter *spec.API, services []string, weights []int32) *istioclientnetworking.VirtualService {

return k8s.VirtualService(&k8s.VirtualServiceSpec{
Name: trafficsplitter.Name,
Gateways: []string{"apis-gateway"},
Expand Down
9 changes: 9 additions & 0 deletions pkg/operator/resources/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ func Deploy(projectBytes []byte, configPath string, configBytes []byte, force bo
err = errors.Append(err, fmt.Sprintf("\n\napi configuration schema can be found here: https://docs.cortex.dev/v/%s/deployments/api-configuration", consts.CortexVersionMinor))
return nil, err
}

//order apiconfigs first syncAPIs then TrafficSplit
apiConfigs = append(ApisWithoutAPISplitter(apiConfigs), ApisWithoutSyncAPI(apiConfigs)...)

results := make([]schema.DeployResult, len(apiConfigs))
for i, apiConfig := range apiConfigs {
api, msg, err := UpdateAPI(&apiConfig, projectID, force)
Expand Down Expand Up @@ -172,6 +176,11 @@ func DeleteAPI(apiName string, keepCache bool) (*schema.DeleteResponse, error) {
if err != nil {
return nil, err
}
if deployedResource.Kind == userconfig.TrafficSplitter {
err := syncapi.DeleteAPI(apiName, keepCache)
if err != nil {
return nil, err
}
} else {
return nil, ErrorOperationNotSupportedForKind(deployedResource.Kind) // unexpected
}
Expand Down
15 changes: 13 additions & 2 deletions pkg/operator/resources/validations.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func ValidateClusterAPIs(apis []userconfig.API, projectFiles spec.ProjectFiles)

didPrintWarning := false

withoutAPISplitter := apisWithoutAPISplitter(apis)
withoutAPISplitter := ApisWithoutAPISplitter(apis)
for i := range apis {
api := &apis[i]
fmt.Println(api)
Expand Down Expand Up @@ -251,7 +251,7 @@ func getValidationK8sResources() ([]istioclientnetworking.VirtualService, *kreso
return virtualServices, maxMem, err
}

func apisWithoutAPISplitter(apis []userconfig.API) []userconfig.API {
func ApisWithoutAPISplitter(apis []userconfig.API) []userconfig.API {
withoutAPISplitter := []userconfig.API{}
for _, api := range apis {
if api.Kind != userconfig.APISplitterKind {
Expand All @@ -262,6 +262,17 @@ func apisWithoutAPISplitter(apis []userconfig.API) []userconfig.API {
return withoutAPISplitter
}

func ApisWithoutSyncAPI(apis []userconfig.API) []userconfig.API {
withoutSyncAPI := []userconfig.API{}
for _, api := range apis {
if api.Kind != userconfig.SyncAPIKind {
withoutSyncAPI = append(withoutSyncAPI, api)
}

}
return withoutSyncAPI
}

func checkIfAPIExist(trafficSplitterAPIs []*userconfig.TrafficSplitter, apis []userconfig.API) (bool, error) {

// TO DOOOOOO
Expand Down