diff --git a/flyteadmin/go.mod b/flyteadmin/go.mod index 1d2b201bb2..8dd5745311 100644 --- a/flyteadmin/go.mod +++ b/flyteadmin/go.mod @@ -25,7 +25,7 @@ require ( github.com/jmespath/go-jmespath v0.3.0 // indirect github.com/kelseyhightower/envconfig v1.4.0 // indirect github.com/lib/pq v1.3.0 - github.com/lyft/flyteidl v0.17.24 + github.com/lyft/flyteidl v0.17.27 github.com/lyft/flytepropeller v0.2.13 github.com/lyft/flytestdlib v0.3.2 github.com/magiconair/properties v1.8.1 diff --git a/flyteadmin/go.sum b/flyteadmin/go.sum index 62af0a3f53..3ed3568dfc 100644 --- a/flyteadmin/go.sum +++ b/flyteadmin/go.sum @@ -32,8 +32,6 @@ github.com/Azure/azure-sdk-for-go v32.5.0+incompatible/go.mod h1:9XXNKU+eRnpl9mo github.com/Azure/azure-sdk-for-go v38.2.0+incompatible h1:ZeCdp1E/V5lI8oLR/BjWQh0OW9aFBYlgXGKRVIWNPXY= github.com/Azure/azure-sdk-for-go v38.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v39.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go v39.1.0+incompatible h1:ZwZgxG+8jLMJbY2NN1e8wiqE+/j4GiuHEc7U5wvPR94= -github.com/Azure/azure-sdk-for-go v39.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v40.2.0+incompatible h1:JVGI3ws5ouCNwtQtwProxSff9uf2XiH/K8ydhuNhL1I= github.com/Azure/azure-sdk-for-go v40.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v40.3.0+incompatible h1:NthZg3psrLxvQLN6rVm07pZ9mv2wvGNaBNGQ3fnPvLE= @@ -42,8 +40,6 @@ github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= github.com/Azure/go-autorest/autorest v0.9.4 h1:1cM+NmKw91+8h5vfjgzK4ZGLuN72k87XVZBWyGwNjUM= github.com/Azure/go-autorest/autorest v0.9.4/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0= -github.com/Azure/go-autorest/autorest v0.9.5 h1:IvOB+EPvwfzDNJBPe1i3wtnNKl1d/LJ+tweb0N1H3hg= -github.com/Azure/go-autorest/autorest v0.9.5/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= github.com/Azure/go-autorest/autorest v0.10.0 h1:mvdtztBqcL8se7MdrUweNieTNi4kfNG6GOJuurQJpuY= github.com/Azure/go-autorest/autorest v0.10.0/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= github.com/Azure/go-autorest/autorest/adal v0.5.0 h1:q2gDruN08/guU9vAjuPWff0+QIrpH6ediguzdAzXAUU= @@ -106,8 +102,6 @@ github.com/aws/aws-sdk-go v1.23.4/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN github.com/aws/aws-sdk-go v1.28.9 h1:grIuBQc+p3dTRXerh5+2OxSuWFi0iXuxbFdTSg0jaW0= github.com/aws/aws-sdk-go v1.28.9/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.28.11/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.29.2 h1:muUfu006FBFvEaDzt4Wq6Ng9E7ufedf8zrB4hmY65QA= -github.com/aws/aws-sdk-go v1.29.2/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg= github.com/aws/aws-sdk-go v1.29.20 h1:vAHJhARpdbdeJstTVaugeHgvVj5lBnfz3blbbD24gfo= github.com/aws/aws-sdk-go v1.29.20/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg= github.com/aws/aws-sdk-go v1.29.23 h1:wtiGLOzxAP755OfuVTDIy/NbUIYEDxbIbBEDfNhUpeU= @@ -267,6 +261,7 @@ github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85n github.com/go-redis/redis v6.15.7+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.0.5/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= @@ -331,15 +326,13 @@ github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hf github.com/google/readahead v0.0.0-20161222183148-eaceba169032/go.mod h1:qYysrqQXuV4tzsizt4oOQ6mrBZQ0xnQXP3ylXX8Jk5Y= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.3.1 h1:WeAefnSUHlBb0iJKwxFDZdbfGwkd7xRNuV+IpXMJhYk= github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU= -github.com/googleapis/gnostic v0.4.1 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyycI+I= -github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -373,8 +366,6 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.12.2 h1:D0EVSTwQoQOyfY35QNSuPJA4jpZRtkoGYWQMB7XNg5o= github.com/grpc-ecosystem/grpc-gateway v1.12.2/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c= -github.com/grpc-ecosystem/grpc-gateway v1.13.0 h1:sBDQoHXrOlfPobnKw69FIKa1wg9qsLLvvQ/Y19WtFgI= -github.com/grpc-ecosystem/grpc-gateway v1.13.0/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c= github.com/grpc-ecosystem/grpc-gateway v1.14.2 h1:SG3eXGmMVahaP4UtKsO/gPQpkovjXOmxXNd7sJlhxNs= github.com/grpc-ecosystem/grpc-gateway v1.14.2/go.mod h1:6CwZWGDSPRJidgKAtJVvND6soZe6fT7iteq8wDPdhb0= github.com/grpc-ecosystem/grpc-gateway v1.14.3 h1:OCJlWkOUoTnl0neNGlf4fUm3TmbEtguw7vR+nGtnDjY= @@ -384,6 +375,7 @@ github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHh github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= @@ -440,7 +432,6 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= @@ -456,26 +447,12 @@ github.com/lyft/apimachinery v0.0.0-20191031200210-047e3ea32d7f h1:PGuAMDzAen0Au github.com/lyft/apimachinery v0.0.0-20191031200210-047e3ea32d7f/go.mod h1:llRdnznGEAqC3DcNm6yEj472xaFVfLM7hnYofMb12tQ= github.com/lyft/datacatalog v0.2.1/go.mod h1:ktrPvzTDUwHO5Lv0hLH38zLHnOJ++rGoAO0iQ/sIPJ4= github.com/lyft/flyteidl v0.17.0/go.mod h1:/zQXxuHO11u/saxTTZc8oYExIGEShXB+xCB1/F1Cu20= -github.com/lyft/flyteidl v0.17.3 h1:ihMrx+ipLkKtJ4h9s32JcUgdPW+VmcsFq3k0yoJc8FY= -github.com/lyft/flyteidl v0.17.3/go.mod h1:/zQXxuHO11u/saxTTZc8oYExIGEShXB+xCB1/F1Cu20= github.com/lyft/flyteidl v0.17.6/go.mod h1:/zQXxuHO11u/saxTTZc8oYExIGEShXB+xCB1/F1Cu20= -github.com/lyft/flyteidl v0.17.7 h1:tDzRjcUUepGCnR/8/VLdsD9toW28nJ969qzcrJe5O5c= -github.com/lyft/flyteidl v0.17.7/go.mod h1:/zQXxuHO11u/saxTTZc8oYExIGEShXB+xCB1/F1Cu20= github.com/lyft/flyteidl v0.17.8 h1:/bZS1K3FO45EMamNrs4Eo6WYQf1TO5bNyNTIUO6cXM0= github.com/lyft/flyteidl v0.17.8/go.mod h1:/zQXxuHO11u/saxTTZc8oYExIGEShXB+xCB1/F1Cu20= -github.com/lyft/flyteidl v0.17.20 h1:SYhu5BRyc81fQQeCvn1pt8Nhd2BBM7JOmDnvUMwGHj4= -github.com/lyft/flyteidl v0.17.20/go.mod h1:/zQXxuHO11u/saxTTZc8oYExIGEShXB+xCB1/F1Cu20= -github.com/lyft/flyteidl v0.17.23-0.20200401223233-5fcbfe070fad h1:T5lJx1on3Qy981L19GdMwHHiAuMCWXLxHQCFk+JW4B0= -github.com/lyft/flyteidl v0.17.23-0.20200401223233-5fcbfe070fad/go.mod h1:/zQXxuHO11u/saxTTZc8oYExIGEShXB+xCB1/F1Cu20= -github.com/lyft/flyteidl v0.17.23/go.mod h1:/zQXxuHO11u/saxTTZc8oYExIGEShXB+xCB1/F1Cu20= -github.com/lyft/flyteidl v0.17.24 h1:N5mmk2/0062VjbIeUXLHWVZwkxGW20RdZtshaea2nL0= -github.com/lyft/flyteidl v0.17.24/go.mod h1:/zQXxuHO11u/saxTTZc8oYExIGEShXB+xCB1/F1Cu20= -github.com/lyft/flyteplugins v0.3.10/go.mod h1:FOSo04q4EheU6lm0oZFvfYAWgjrum/BDUK+mUT7qDFA= +github.com/lyft/flyteidl v0.17.27 h1:0EdSHauzdPEYmubYib/XC6fLb+srzP4yDRN1P9o4W/I= +github.com/lyft/flyteidl v0.17.27/go.mod h1:/zQXxuHO11u/saxTTZc8oYExIGEShXB+xCB1/F1Cu20= github.com/lyft/flyteplugins v0.3.11/go.mod h1:FOSo04q4EheU6lm0oZFvfYAWgjrum/BDUK+mUT7qDFA= -github.com/lyft/flytepropeller v0.1.30 h1:g55bD3aMMba4WDiBE7SLFEElutPdkEtoFQkgN59OX+M= -github.com/lyft/flytepropeller v0.1.30/go.mod h1:SgMi8FEw9K8BZHggUXIQ5Maw8LF9ymgtNTDjNahmXOc= -github.com/lyft/flytepropeller v0.2.11-0.20200306015502-add9e8715ad8 h1:rnzkfiIkmMXZ4BcLegruLPT6gfVHV7qk/UMQySxCEOM= -github.com/lyft/flytepropeller v0.2.11-0.20200306015502-add9e8715ad8/go.mod h1:Kw1UZ5iwoCW4AviqUSZTryXp35dOo0w7sdjTs3Wb9ho= github.com/lyft/flytepropeller v0.2.13 h1:RDFM8ps5bHWdHYK87NLyYX4iyF16ahkxerI0X9DZSfM= github.com/lyft/flytepropeller v0.2.13/go.mod h1:QJ9txCCxHnzvwQoG4TbcldVs1in4+C943prLZVDmmIA= github.com/lyft/flytestdlib v0.3.0 h1:nIkX4MlyYdcLLzaF35RI2P5BhARt+qMgHoFto8eVNzU= @@ -537,12 +514,14 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.3.0/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.8.1 h1:C5Dqfs/LeauYDX0jJXIe2SWmwCbGzx9yF8C8xy3Lh34= github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= @@ -576,8 +555,6 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.3.0 h1:miYCvYqFXtl/J9FIy8eNpBfYthAEFg+Ys0XyUVEcDsc= github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.4.1 h1:FFSuS004yOQEtDdTq+TAOLP5xUq63KqAFYyOi8zA+Y8= -github.com/prometheus/client_golang v1.4.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.5.0 h1:Ctq0iGpCmr3jeP77kbF2UxgvRwzWWz+4Bh9/vJTyg1A= github.com/prometheus/client_golang v1.5.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= @@ -728,8 +705,6 @@ golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200117160349-530e935923ad h1:Jh8cai0fqIK+f6nG0UgPW5wFk8wmiMhM3AyciDBdtQg= golang.org/x/crypto v0.0.0-20200117160349-530e935923ad/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200210222208-86ce3cb69678 h1:wCWoJcFExDgyYx2m2hpHgwz8W3+FPdfldvIgzqDIhyg= -golang.org/x/crypto v0.0.0-20200210222208-86ce3cb69678/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 h1:xMPOj6Pz6UipU1wXLkrtqpHbR0AVFnyPEQq/wRWz9lM= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4 h1:QmwruyY+bKbDDL0BaglrbZABEali68eoMFhTZpCjYVA= @@ -916,6 +891,7 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.0.1/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= +gomodules.xyz/jsonpatch/v2 v2.1.0 h1:Phva6wqu+xR//Njw6iorylFFgn/z547tw5Ne3HZPQ+k= gomodules.xyz/jsonpatch/v2 v2.1.0/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= @@ -929,8 +905,6 @@ google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEn google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.1-0.20200117000758-b4cd77d6a56c h1:AEolErvorE7ZBfygG7x31pQd6lKIuOq6xRnTJFCfJNU= -google.golang.org/api v0.15.1-0.20200117000758-b4cd77d6a56c/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.16.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.17.0 h1:0q95w+VuFtv4PAx4PZVQdBMmYbaCHbnfKaEiDIcVyag= google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= @@ -994,6 +968,7 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= @@ -1007,8 +982,6 @@ gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.51.1 h1:GyboHr4UqMiLUybYjd22ZjQIKEJEpgtLXtuGbR21Oho= gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.52.0 h1:j+Lt/M1oPPejkniCg1TkWE2J3Eh1oZTsHSXzMTzUXn4= -gopkg.in/ini.v1 v1.52.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.54.0 h1:oM5ElzbIi7gwLnNbPX2M25ED1vSAK3B6dex50eS/6Fs= gopkg.in/ini.v1 v1.54.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo= @@ -1044,6 +1017,7 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/apiextensions-apiserver v0.0.0-20190918161926-8f644eb6e783 h1:V6ndwCPoao1yZ52agqOKaUAl7DYWVGiXjV7ePA2i610= k8s.io/apiextensions-apiserver v0.0.0-20190918161926-8f644eb6e783/go.mod h1:xvae1SZB3E17UpV59AWc271W/Ph25N+bjPyR63X6tPY= +k8s.io/apiextensions-apiserver v0.17.2 h1:cP579D2hSZNuO/rZj9XFRzwJNYb41DbNANJb6Kolpss= k8s.io/apiextensions-apiserver v0.17.2/go.mod h1:4KdMpjkEjjDI2pPfBA15OscyNldHWdBCfsWMDWAmSTs= k8s.io/apiserver v0.0.0-20190918160949-bfa5e2e684ad/go.mod h1:XPCXEwhjaFN29a8NldXA901ElnKeKLrLtREO9ZhFyhg= k8s.io/apiserver v0.17.2/go.mod h1:lBmw/TtQdtxvrTk0e2cgtOxHizXI+d0mmGQURIHQZlo= @@ -1063,11 +1037,10 @@ k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= +k8s.io/kube-openapi v0.0.0-20200204173128-addea2498afe h1:GOfbcWvX5wW2vcfNch83xYp9SDZjRgAJk+t373yaHKk= k8s.io/kube-openapi v0.0.0-20200204173128-addea2498afe/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= -k8s.io/utils v0.0.0-20200109141947-94aeca20bf09 h1:sz6xjn8QP74104YNmJpzLbJ+a3ZtHt0tkD0g8vpdWNw= -k8s.io/utils v0.0.0-20200109141947-94aeca20bf09/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20200124190032-861946025e34 h1:HjlUD6M0K3P8nRXmr2B9o4F9dUy9TCj/aEpReeyi6+k= k8s.io/utils v0.0.0-20200124190032-861946025e34/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20200229041039-0a110f9eb7ab h1:I3f2hcBrepGRXI1z4sukzAb8w1R4eqbsHrAsx06LGYM= @@ -1080,8 +1053,6 @@ modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/controller-runtime v0.3.1-0.20191029211253-40070e2a1958 h1:unm3QV/Hodw9J7L52GBjiB9yL+SA/A+s/xjGtjz021c= -sigs.k8s.io/controller-runtime v0.3.1-0.20191029211253-40070e2a1958/go.mod h1:p2vzQ3RuSVv9YR4AcM0y8TKHQA+0oLXazKFt6Z0OdS8= sigs.k8s.io/controller-runtime v0.4.0/go.mod h1:ApC79lpY3PHW9xj/w9pj+lYkLgwAAUZwfXkME1Lajns= sigs.k8s.io/controller-runtime v0.5.0 h1:CbqIy5fbUX+4E9bpnBFd204YAzRYlM9SWW77BbrcDQo= sigs.k8s.io/controller-runtime v0.5.0/go.mod h1:REiJzC7Y00U+2YkMbT8wxgrsX5USpXKGhb2sCtAXiT8= @@ -1091,8 +1062,6 @@ sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:w sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA= sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06/go.mod h1:/ULNhyfzRopfcjskuui0cTITekDduZ7ycKN3oUT9R18= sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= -sigs.k8s.io/testing_frameworks v0.1.1 h1:cP2l8fkA3O9vekpy5Ks8mmA0NW/F7yBdXf8brkWhVrs= -sigs.k8s.io/testing_frameworks v0.1.1/go.mod h1:VVBKrHmJ6Ekkfz284YKhQePcdycOzNH9qL6ht1zEr/U= sigs.k8s.io/testing_frameworks v0.1.2/go.mod h1:ToQrwSC3s8Xf/lADdZp3Mktcql9CG0UAmdJG9th5i0w= sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= diff --git a/flyteadmin/pkg/common/entity.go b/flyteadmin/pkg/common/entity.go index 5784dabfa9..56eda411bb 100644 --- a/flyteadmin/pkg/common/entity.go +++ b/flyteadmin/pkg/common/entity.go @@ -7,13 +7,14 @@ import ( type Entity = string const ( - Execution = "e" - LaunchPlan = "l" - NodeExecution = "ne" - NodeExecutionEvent = "nee" - Task = "t" - TaskExecution = "te" - Workflow = "w" + Execution = "e" + LaunchPlan = "l" + NodeExecution = "ne" + NodeExecutionEvent = "nee" + Task = "t" + TaskExecution = "te" + Workflow = "w" + NamedEntityMetadata = "nem" ) // ResourceTypeToEntity maps a resource type to an entity suitable for use with Database filters diff --git a/flyteadmin/pkg/common/filters.go b/flyteadmin/pkg/common/filters.go index 26b957de95..67108ced5f 100644 --- a/flyteadmin/pkg/common/filters.go +++ b/flyteadmin/pkg/common/filters.go @@ -5,9 +5,8 @@ import ( "context" "fmt" - "github.com/lyft/flytestdlib/logger" - "github.com/lyft/flyteadmin/pkg/errors" + "github.com/lyft/flytestdlib/logger" "google.golang.org/grpc/codes" ) @@ -132,6 +131,8 @@ func GetInvalidRepeatedValueFilterErr(expression FilterExpression) error { type InlineFilter interface { // Returns the entity for which this filter should be applied. GetEntity() Entity + // Returns the column filtered on. + GetField() string // Generates fields necessary to add a filter to a gorm database query. GetGormQueryExpr() (GormQueryExpr, error) // Generates fields necessary to add a filter on a gorm database join query. @@ -153,7 +154,11 @@ func (f *inlineFilterImpl) GetEntity() Entity { return f.entity } -func (f *inlineFilterImpl) GetGormQueryExpr() (GormQueryExpr, error) { +func (f *inlineFilterImpl) GetField() string { + return f.field +} + +func (f *inlineFilterImpl) getGormQueryExpr(formattedField string) (GormQueryExpr, error) { // ValueIn is special because it uses repeating values. if f.function == ValueIn { @@ -168,44 +173,44 @@ func (f *inlineFilterImpl) GetGormQueryExpr() (GormQueryExpr, error) { case Contains: return GormQueryExpr{ // WHERE field LIKE %value% - Query: fmt.Sprintf(containsQuery, f.field), + Query: fmt.Sprintf(containsQuery, formattedField), // args renders to something like: "%value%" Args: fmt.Sprintf(containsArgs, f.value), }, nil case GreaterThan: return GormQueryExpr{ // WHERE field > value - Query: fmt.Sprintf(greaterThanQuery, f.field), + Query: fmt.Sprintf(greaterThanQuery, formattedField), Args: f.value, }, nil case GreaterThanOrEqual: return GormQueryExpr{ // WHERE field >= value - Query: fmt.Sprintf(greaterThanOrEqualQuery, f.field), + Query: fmt.Sprintf(greaterThanOrEqualQuery, formattedField), Args: f.value, }, nil case LessThan: return GormQueryExpr{ // WHERE field < value - Query: fmt.Sprintf(lessThanQuery, f.field), + Query: fmt.Sprintf(lessThanQuery, formattedField), Args: f.value, }, nil case LessThanOrEqual: return GormQueryExpr{ // WHERE field <= value - Query: fmt.Sprintf(lessThanOrEqualQuery, f.field), + Query: fmt.Sprintf(lessThanOrEqualQuery, formattedField), Args: f.value, }, nil case Equal: return GormQueryExpr{ // WHERE field = value - Query: fmt.Sprintf(equalQuery, f.field), + Query: fmt.Sprintf(equalQuery, formattedField), Args: f.value, }, nil case NotEqual: return GormQueryExpr{ // WHERE field <> value - Query: fmt.Sprintf(notEqualQuery, f.field), + Query: fmt.Sprintf(notEqualQuery, formattedField), Args: f.value, }, nil } @@ -213,9 +218,13 @@ func (f *inlineFilterImpl) GetGormQueryExpr() (GormQueryExpr, error) { return GormQueryExpr{}, GetUnsupportedFilterExpressionErr(f.function) } +func (f *inlineFilterImpl) GetGormQueryExpr() (GormQueryExpr, error) { + return f.getGormQueryExpr(f.field) +} + func (f *inlineFilterImpl) GetGormJoinTableQueryExpr(tableName string) (GormQueryExpr, error) { - f.field = fmt.Sprintf(joinArgsFormat, tableName, f.field) - return f.GetGormQueryExpr() + formattedField := fmt.Sprintf(joinArgsFormat, tableName, f.field) + return f.getGormQueryExpr(formattedField) } func customizeField(field string, entity Entity) string { @@ -284,3 +293,33 @@ func NewMapFilter(filter map[string]interface{}) MapFilter { filter: filter, } } + +const queryWithDefaultFmt = "COALESCE(%s, %v)" + +type withDefaultValueFilter struct { + inlineFilterImpl + defaultValue interface{} +} + +func (f *withDefaultValueFilter) GetGormQueryExpr() (GormQueryExpr, error) { + formattedField := fmt.Sprintf(queryWithDefaultFmt, f.GetField(), f.defaultValue) + return f.getGormQueryExpr(formattedField) +} + +func (f *withDefaultValueFilter) GetGormJoinTableQueryExpr(tableName string) (GormQueryExpr, error) { + formattedField := fmt.Sprintf(queryWithDefaultFmt, fmt.Sprintf(joinArgsFormat, tableName, f.GetField()), f.defaultValue) + return f.getGormQueryExpr(formattedField) +} + +func NewWithDefaultValueFilter(defaultValue interface{}, filter InlineFilter) (InlineFilter, error) { + inlineFilter, ok := filter.(*inlineFilterImpl) + if !ok { + return nil, errors.NewFlyteAdminErrorf(codes.Internal, + "Unable to create default value filter for [%s] because the system encountered an unknown filter type", + filter.GetField()) + } + return &withDefaultValueFilter{ + inlineFilterImpl: *inlineFilter, + defaultValue: defaultValue, + }, nil +} diff --git a/flyteadmin/pkg/common/filters_test.go b/flyteadmin/pkg/common/filters_test.go index d9c94316cd..efba8d2911 100644 --- a/flyteadmin/pkg/common/filters_test.go +++ b/flyteadmin/pkg/common/filters_test.go @@ -129,3 +129,22 @@ func TestMapFilter(t *testing.T) { } assert.EqualValues(t, mapFilterValue, NewMapFilter(mapFilterValue).GetFilter()) } + +func TestWithDefaultValueFilter(t *testing.T) { + filter, err := NewSingleValueFilter(NamedEntityMetadata, Equal, "state", 1) + assert.NoError(t, err) + + filterWithDefaultValue, err := NewWithDefaultValueFilter(0, filter) + assert.NoError(t, err) + + queryExpression, err := filterWithDefaultValue.GetGormQueryExpr() + assert.NoError(t, err) + assert.Equal(t, "COALESCE(state, 0) = ?", queryExpression.Query) + assert.Equal(t, 1, queryExpression.Args) + + queryExpression, err = filterWithDefaultValue.GetGormJoinTableQueryExpr( + "named_entity_metadata") + assert.NoError(t, err) + assert.Equal(t, "COALESCE(named_entity_metadata.state, 0) = ?", queryExpression.Query) + assert.Equal(t, 1, queryExpression.Args) +} diff --git a/flyteadmin/pkg/manager/impl/named_entity_manager.go b/flyteadmin/pkg/manager/impl/named_entity_manager.go index dfec0d59c9..b44476779e 100644 --- a/flyteadmin/pkg/manager/impl/named_entity_manager.go +++ b/flyteadmin/pkg/manager/impl/named_entity_manager.go @@ -3,6 +3,7 @@ package impl import ( "context" "strconv" + "strings" "github.com/lyft/flytestdlib/contextutils" @@ -22,6 +23,8 @@ import ( "github.com/lyft/flytestdlib/promutils" ) +const state = "state" + type NamedEntityMetrics struct { Scope promutils.Scope } @@ -65,6 +68,31 @@ func (m *NamedEntityManager) GetNamedEntity(ctx context.Context, request admin.N return util.GetNamedEntity(ctx, m.db, request.ResourceType, *request.Id) } +func (m *NamedEntityManager) updateQueryFilters(identityFilters []common.InlineFilter, requestFilters string) ( + []common.InlineFilter, error) { + if len(requestFilters) == 0 { + return identityFilters, nil + } + additionalFilters, err := util.ParseFilters(requestFilters, common.NamedEntityMetadata) + if err != nil { + return nil, err + } + var finalizedFilters = identityFilters + for _, filter := range additionalFilters { + if strings.Contains(filter.GetField(), state) { + filterWithDefaultValue, err := common.NewWithDefaultValueFilter( + strconv.Itoa(int(admin.NamedEntityState_NAMED_ENTITY_ACTIVE)), filter) + if err != nil { + return nil, err + } + finalizedFilters = append(finalizedFilters, filterWithDefaultValue) + } else { + finalizedFilters = append(finalizedFilters, filter) + } + } + return finalizedFilters, nil +} + func (m *NamedEntityManager) ListNamedEntities(ctx context.Context, request admin.NamedEntityListRequest) ( *admin.NamedEntityList, error) { if err := validation.ValidateNamedEntityListRequest(request); err != nil { @@ -73,13 +101,20 @@ func (m *NamedEntityManager) ListNamedEntities(ctx context.Context, request admi } ctx = contextutils.WithProjectDomain(ctx, request.Project, request.Domain) - filters, err := util.GetDbFilters(util.FilterSpec{ + identifierFilters, err := util.GetDbFilters(util.FilterSpec{ Project: request.Project, Domain: request.Domain, }, common.ResourceTypeToEntity[request.ResourceType]) if err != nil { return nil, err } + // HACK: In order to filter by state (if requested) - we need to amend the filter to use COALESCE + // e.g. eq(state, 1) becomes 'WHERE (COALESCE(state, 0) = '1')' since not every NamedEntity necessarily + // has an entry, and therefore the default state value '0' (active), should be assumed. + filters, err := m.updateQueryFilters(identifierFilters, request.Filters) + if err != nil { + return nil, err + } var sortParameter common.SortParameter if request.SortBy != nil { sortParameter, err = common.NewSortParameter(*request.SortBy) diff --git a/flyteadmin/pkg/manager/impl/named_entity_manager_test.go b/flyteadmin/pkg/manager/impl/named_entity_manager_test.go index 8d61737f8d..8c46d356f3 100644 --- a/flyteadmin/pkg/manager/impl/named_entity_manager_test.go +++ b/flyteadmin/pkg/manager/impl/named_entity_manager_test.go @@ -4,6 +4,8 @@ import ( "context" "testing" + "github.com/lyft/flyteadmin/pkg/common" + "github.com/lyft/flyteadmin/pkg/manager/impl/testutils" "github.com/lyft/flyteadmin/pkg/repositories" "github.com/lyft/flyteadmin/pkg/repositories/interfaces" @@ -84,6 +86,26 @@ func TestNamedEntityManager_Get_BadRequest(t *testing.T) { assert.Nil(t, response) } +func TestNamedEntityManager_UpdateQueryFilters(t *testing.T) { + identityFilter, err := common.NewSingleValueFilter(common.NamedEntityMetadata, common.Equal, "project", "proj") + assert.NoError(t, err) + + repository := getMockRepositoryForNETest() + manager := NewNamedEntityManager(repository, getMockConfigForNETest(), mockScope.NewTestScope()) + updatedFilters, err := manager.(*NamedEntityManager).updateQueryFilters([]common.InlineFilter{ + identityFilter, + }, "eq(state, 0)") + assert.NoError(t, err) + assert.Len(t, updatedFilters, 2) + + assert.Equal(t, "project", updatedFilters[0].GetField()) + assert.Equal(t, "state", updatedFilters[1].GetField()) + queryExp, err := updatedFilters[1].GetGormQueryExpr() + assert.NoError(t, err) + assert.Equal(t, "COALESCE(state, 0) = ?", queryExp.Query) + assert.Equal(t, "0", queryExp.Args) +} + func TestNamedEntityManager_Update(t *testing.T) { repository := getMockRepositoryForNETest() manager := NewNamedEntityManager(repository, getMockConfigForNETest(), mockScope.NewTestScope()) diff --git a/flyteadmin/pkg/manager/impl/util/filters.go b/flyteadmin/pkg/manager/impl/util/filters.go index 03e90de516..037969d6c2 100644 --- a/flyteadmin/pkg/manager/impl/util/filters.go +++ b/flyteadmin/pkg/manager/impl/util/filters.go @@ -52,12 +52,13 @@ const filterFieldEntityPrefixFmt = "%s." const secondsFormat = "%vs" var filterFieldEntityPrefix = map[string]common.Entity{ - "task": common.Task, - "workflow": common.Workflow, - "launch_plan": common.LaunchPlan, - "execution": common.Execution, - "node_execution": common.NodeExecution, - "task_execution": common.TaskExecution, + "task": common.Task, + "workflow": common.Workflow, + "launch_plan": common.LaunchPlan, + "execution": common.Execution, + "node_execution": common.NodeExecution, + "task_execution": common.TaskExecution, + "named_entity_metadata": common.NamedEntityMetadata, } func parseField(field string, primaryEntity common.Entity) (common.Entity, string) { diff --git a/flyteadmin/pkg/manager/impl/validation/named_entity_validator.go b/flyteadmin/pkg/manager/impl/validation/named_entity_validator.go index 6f80c74e04..5d94cd06d9 100644 --- a/flyteadmin/pkg/manager/impl/validation/named_entity_validator.go +++ b/flyteadmin/pkg/manager/impl/validation/named_entity_validator.go @@ -1,8 +1,11 @@ package validation import ( + "github.com/lyft/flyteadmin/pkg/errors" "github.com/lyft/flyteadmin/pkg/manager/impl/shared" "github.com/lyft/flyteidl/gen/pb-go/flyteidl/admin" + "github.com/lyft/flyteidl/gen/pb-go/flyteidl/core" + "google.golang.org/grpc/codes" ) func ValidateNamedEntityGetRequest(request admin.NamedEntityGetRequest) error { @@ -25,6 +28,13 @@ func ValidateNamedEntityUpdateRequest(request admin.NamedEntityUpdateRequest) er if request.Metadata == nil { return shared.GetMissingArgumentError(shared.Metadata) } + + // Anything but the default state is only permitted for workflow resources. + if request.Metadata.State != admin.NamedEntityState_NAMED_ENTITY_ACTIVE && + request.ResourceType != core.ResourceType_WORKFLOW { + return errors.NewFlyteAdminErrorf(codes.InvalidArgument, + "Only workflow name entities can have their state updated") + } return nil } diff --git a/flyteadmin/pkg/manager/impl/validation/named_entity_validator_test.go b/flyteadmin/pkg/manager/impl/validation/named_entity_validator_test.go index c62a9f14d7..1f6c24f147 100644 --- a/flyteadmin/pkg/manager/impl/validation/named_entity_validator_test.go +++ b/flyteadmin/pkg/manager/impl/validation/named_entity_validator_test.go @@ -3,6 +3,9 @@ package validation import ( "testing" + "github.com/lyft/flyteadmin/pkg/errors" + "google.golang.org/grpc/codes" + "github.com/lyft/flyteidl/gen/pb-go/flyteidl/admin" "github.com/lyft/flyteidl/gen/pb-go/flyteidl/core" "github.com/stretchr/testify/assert" @@ -105,6 +108,28 @@ func TestValidateNamedEntityUpdateRequest(t *testing.T) { Name: "name", }, })) + assert.Equal(t, codes.InvalidArgument, ValidateNamedEntityUpdateRequest(admin.NamedEntityUpdateRequest{ + ResourceType: core.ResourceType_LAUNCH_PLAN, + Id: &admin.NamedEntityIdentifier{ + Project: "project", + Domain: "domain", + Name: "name", + }, + Metadata: &admin.NamedEntityMetadata{ + State: admin.NamedEntityState_NAMED_ENTITY_ARCHIVED, + }, + }).(errors.FlyteAdminError).Code()) + assert.Nil(t, ValidateNamedEntityUpdateRequest(admin.NamedEntityUpdateRequest{ + ResourceType: core.ResourceType_WORKFLOW, + Id: &admin.NamedEntityIdentifier{ + Project: "project", + Domain: "domain", + Name: "name", + }, + Metadata: &admin.NamedEntityMetadata{ + State: admin.NamedEntityState_NAMED_ENTITY_ARCHIVED, + }, + })) } func TestValidateNamedEntityListRequest(t *testing.T) { diff --git a/flyteadmin/pkg/manager/impl/workflow_manager.go b/flyteadmin/pkg/manager/impl/workflow_manager.go index 1a6e49bbfe..f8a7555d10 100644 --- a/flyteadmin/pkg/manager/impl/workflow_manager.go +++ b/flyteadmin/pkg/manager/impl/workflow_manager.go @@ -336,26 +336,6 @@ func (w *WorkflowManager) ListWorkflowIdentifiers(ctx context.Context, request a } -func (w *WorkflowManager) UpdateWorkflow(ctx context.Context, request admin.WorkflowUpdateRequest) ( - *admin.WorkflowUpdateResponse, error) { - if err := validation.ValidateIdentifier(request.Id, common.Workflow); err != nil { - logger.Debugf(ctx, "invalid identifier [%+v]: %v", request.Id, err) - return nil, err - } - ctx = getWorkflowContext(ctx, request.Id) - workflowModel, err := util.GetWorkflowModel(ctx, w.db, *request.Id) - if err != nil { - return nil, err - } - stateInt := int32(request.State) - workflowModel.State = &stateInt - err = w.db.WorkflowRepo().Update(ctx, workflowModel) - if err != nil { - return nil, err - } - return &admin.WorkflowUpdateResponse{}, nil -} - func NewWorkflowManager( db repositories.RepositoryInterface, config runtimeInterfaces.Configuration, diff --git a/flyteadmin/pkg/manager/impl/workflow_manager_test.go b/flyteadmin/pkg/manager/impl/workflow_manager_test.go index e93cbbf9ac..1e51628670 100644 --- a/flyteadmin/pkg/manager/impl/workflow_manager_test.go +++ b/flyteadmin/pkg/manager/impl/workflow_manager_test.go @@ -573,40 +573,3 @@ func TestWorkflowManager_ListWorkflowIdentifiers(t *testing.T) { assert.Equal(t, nameValue, entity.Name) } } - -func TestUpdateWorkflow(t *testing.T) { - repository := repositoryMocks.NewMockRepository() - workflowGetFunc := func(input interfaces.GetResourceInput) (models.Workflow, error) { - return models.Workflow{ - BaseModel: models.BaseModel{ - CreatedAt: testutils.MockCreatedAtValue, - }, - WorkflowKey: models.WorkflowKey{ - Project: input.Project, - Domain: input.Domain, - Name: input.Name, - Version: input.Version, - }, - TypedInterface: testutils.GetWorkflowRequestInterfaceBytes(), - RemoteClosureIdentifier: remoteClosureIdentifier, - }, nil - } - repository.WorkflowRepo().(*repositoryMocks.MockWorkflowRepo).SetGetCallback(workflowGetFunc) - - updateFuncCalled := false - workflowUpdatefunc := func(input models.Workflow) error { - updateFuncCalled = true - assert.Equal(t, admin.WorkflowState_WORKFLOW_ARCHIVED, admin.WorkflowState(*input.State)) - return nil - } - repository.WorkflowRepo().(*repositoryMocks.MockWorkflowRepo).SetUpdateCallback(workflowUpdatefunc) - workflowManager := NewWorkflowManager( - repository, getMockWorkflowConfigProvider(), getMockWorkflowCompiler(), commonMocks.GetMockStorageClient(), storagePrefix, - mockScope.NewTestScope()) - _, err := workflowManager.UpdateWorkflow(context.Background(), admin.WorkflowUpdateRequest{ - Id: &workflowIdentifier, - State: admin.WorkflowState_WORKFLOW_ARCHIVED, - }) - assert.NoError(t, err) - assert.True(t, updateFuncCalled) -} diff --git a/flyteadmin/pkg/manager/interfaces/workflow.go b/flyteadmin/pkg/manager/interfaces/workflow.go index ddd5d07a9b..63b828211f 100644 --- a/flyteadmin/pkg/manager/interfaces/workflow.go +++ b/flyteadmin/pkg/manager/interfaces/workflow.go @@ -13,5 +13,4 @@ type WorkflowInterface interface { ListWorkflows(ctx context.Context, request admin.ResourceListRequest) (*admin.WorkflowList, error) ListWorkflowIdentifiers(ctx context.Context, request admin.NamedEntityIdentifierListRequest) ( *admin.NamedEntityIdentifierList, error) - UpdateWorkflow(ctx context.Context, request admin.WorkflowUpdateRequest) (*admin.WorkflowUpdateResponse, error) } diff --git a/flyteadmin/pkg/manager/mocks/workflow.go b/flyteadmin/pkg/manager/mocks/workflow.go index f008e36c06..5de1c031c4 100644 --- a/flyteadmin/pkg/manager/mocks/workflow.go +++ b/flyteadmin/pkg/manager/mocks/workflow.go @@ -39,8 +39,3 @@ func (r *MockWorkflowManager) ListWorkflowIdentifiers(ctx context.Context, reque *admin.NamedEntityIdentifierList, error) { return nil, nil } - -func (r *MockWorkflowManager) UpdateWorkflow(ctx context.Context, request admin.WorkflowUpdateRequest) ( - *admin.WorkflowUpdateResponse, error) { - return nil, nil -} diff --git a/flyteadmin/pkg/repositories/config/migrations.go b/flyteadmin/pkg/repositories/config/migrations.go index fbd513d255..d46cc73a34 100644 --- a/flyteadmin/pkg/repositories/config/migrations.go +++ b/flyteadmin/pkg/repositories/config/migrations.go @@ -169,24 +169,34 @@ var Migrations = []*gormigrate.Migration{ return tx.Exec("ALTER TABLE tasks DROP COLUMN IF EXISTS type").Error }, }, - // Add state to workflow model + // Add state to name entity model { - ID: "2020-04-01-workflow-state", + ID: "2020-04-03-named-entity-state", Migrate: func(tx *gorm.DB) error { - return tx.AutoMigrate(&models.Workflow{}).Error + return tx.AutoMigrate(&models.NamedEntityMetadata{}).Error }, Rollback: func(tx *gorm.DB) error { - return tx.Table("workflows").DropColumn("state").Error + return tx.Table("named_entity_metadata").DropColumn("state").Error }, }, // Set default state value for workflow model { - ID: "2020-04-01-workflow-state-default", + ID: "2020-04-03-named-entity-state-default", + Migrate: func(tx *gorm.DB) error { + return tx.Exec("UPDATE named_entity_metadata SET state = 0").Error + }, + Rollback: func(tx *gorm.DB) error { + return tx.Exec("UPDATE named_entity_metadata set state = NULL").Error + }, + }, + // Modify the workflows table, if necessary + { + ID: "2020-04-03-workflow-state", Migrate: func(tx *gorm.DB) error { - return tx.Exec("UPDATE workflows SET state = 0").Error + return tx.Exec("ALTER TABLE workflows DROP COLUMN IF EXISTS state").Error }, Rollback: func(tx *gorm.DB) error { - return tx.Exec("UPDATE workflows set state = NULL").Error + return tx.Exec("ALTER TABLE workflows ADD COLUMN IF NOT EXISTS state integer;").Error }, }, } diff --git a/flyteadmin/pkg/repositories/gormimpl/common.go b/flyteadmin/pkg/repositories/gormimpl/common.go index abd2a513c6..9e709cf5b7 100644 --- a/flyteadmin/pkg/repositories/gormimpl/common.go +++ b/flyteadmin/pkg/repositories/gormimpl/common.go @@ -8,7 +8,6 @@ import ( adminErrors "github.com/lyft/flyteadmin/pkg/errors" "github.com/lyft/flyteadmin/pkg/repositories/errors" "github.com/lyft/flyteadmin/pkg/repositories/interfaces" - "github.com/lyft/flyteadmin/pkg/repositories/models" "google.golang.org/grpc/codes" ) @@ -19,6 +18,7 @@ const Version = "version" const Closure = "closure" const Description = "description" const ResourceType = "resource_type" +const State = "state" const ProjectID = "project_id" const ProjectName = "project_name" @@ -37,14 +37,15 @@ const filters = "filters" var identifierGroupBy = fmt.Sprintf("%s, %s, %s", Project, Domain, Name) -var entityToModel = map[common.Entity]interface{}{ - common.Execution: models.Execution{}, - common.LaunchPlan: models.LaunchPlan{}, - common.NodeExecution: models.NodeExecution{}, - common.NodeExecutionEvent: models.NodeExecutionEvent{}, - common.Task: models.Task{}, - common.TaskExecution: models.TaskExecution{}, - common.Workflow: models.Workflow{}, +var entityToTableName = map[common.Entity]string{ + common.Execution: "executions", + common.LaunchPlan: "launch_plans", + common.NodeExecution: "node_executions", + common.NodeExecutionEvent: "node_execution_events", + common.Task: "tasks", + common.TaskExecution: "task_executions", + common.Workflow: "workflows", + common.NamedEntityMetadata: "named_entity_metadata", } var innerJoinNodeExecToNodeEvents = fmt.Sprintf( @@ -99,12 +100,11 @@ func applyFilters(tx *gorm.DB, inlineFilters []common.InlineFilter, mapFilters [ func applyScopedFilters(tx *gorm.DB, inlineFilters []common.InlineFilter, mapFilters []common.MapFilter) (*gorm.DB, error) { for _, filter := range inlineFilters { - entityModel, ok := entityToModel[filter.GetEntity()] + tableName, ok := entityToTableName[filter.GetEntity()] if !ok { return nil, adminErrors.NewFlyteAdminErrorf(codes.InvalidArgument, "unrecognized entity in filter expression: %v", filter.GetEntity()) } - tableName := tx.NewScope(entityModel).TableName() gormQueryExpr, err := filter.GetGormJoinTableQueryExpr(tableName) if err != nil { return nil, err diff --git a/flyteadmin/pkg/repositories/gormimpl/named_entity_repo.go b/flyteadmin/pkg/repositories/gormimpl/named_entity_repo.go index 9fa7d5de57..e73e0cfdd8 100644 --- a/flyteadmin/pkg/repositories/gormimpl/named_entity_repo.go +++ b/flyteadmin/pkg/repositories/gormimpl/named_entity_repo.go @@ -44,7 +44,9 @@ var resourceTypeToMetadataJoin = map[core.ResourceType]string{ } func getGroupByForNamedEntity(tableName string) string { - return fmt.Sprintf("%s.%s, %s.%s, %s.%s, %s.%s", tableName, Project, tableName, Domain, tableName, Name, namedEntityMetadataTableName, Description) + return fmt.Sprintf("%s.%s, %s.%s, %s.%s, %s.%s, %s.%s", + tableName, Project, tableName, Domain, tableName, Name, namedEntityMetadataTableName, Description, + namedEntityMetadataTableName, State) } func getSelectForNamedEntity(tableName string, resourceType core.ResourceType) []string { @@ -54,6 +56,7 @@ func getSelectForNamedEntity(tableName string, resourceType core.ResourceType) [ fmt.Sprintf("%s.%s", tableName, Name), fmt.Sprintf("'%d' AS %s", resourceType, ResourceType), fmt.Sprintf("%s.%s", namedEntityMetadataTableName, Description), + fmt.Sprintf("%s.%s", namedEntityMetadataTableName, State), } } @@ -116,7 +119,7 @@ func (r *NamedEntityRepo) Get(ctx context.Context, input interfaces.GetNamedEnti tableName, tableFound := resourceTypeToTableName[input.ResourceType] joinString, joinFound := resourceTypeToMetadataJoin[input.ResourceType] if !tableFound || !joinFound { - return models.NamedEntity{}, adminErrors.NewFlyteAdminErrorf(codes.InvalidArgument, "Cannot get NamedEntity for resource type: %v", input.ResourceType) + return models.NamedEntity{}, adminErrors.NewFlyteAdminErrorf(codes.InvalidArgument, "Cannot get NamedEntityMetadata for resource type: %v", input.ResourceType) } tx := r.db.Table(tableName).Joins(joinString) diff --git a/flyteadmin/pkg/repositories/gormimpl/named_entity_repo_test.go b/flyteadmin/pkg/repositories/gormimpl/named_entity_repo_test.go index 070b613757..4513049fd3 100644 --- a/flyteadmin/pkg/repositories/gormimpl/named_entity_repo_test.go +++ b/flyteadmin/pkg/repositories/gormimpl/named_entity_repo_test.go @@ -4,6 +4,8 @@ import ( "context" "testing" + "github.com/lyft/flyteidl/gen/pb-go/flyteidl/admin" + mocket "github.com/Selvatico/go-mocket" "github.com/lyft/flyteadmin/pkg/repositories/errors" "github.com/lyft/flyteadmin/pkg/repositories/interfaces" @@ -19,6 +21,7 @@ func getMockNamedEntityResponseFromDb(expected models.NamedEntity) map[string]in metadata["domain"] = expected.Domain metadata["name"] = expected.Name metadata["description"] = expected.Description + metadata["state"] = expected.State return metadata } @@ -42,7 +45,7 @@ func TestGetNamedEntity(t *testing.T) { GlobalMock := mocket.Catcher.Reset() GlobalMock.Logging = true GlobalMock.NewMock().WithQuery( - `SELECT workflows.project, workflows.domain, workflows.name, '2' AS resource_type, named_entity_metadata.description FROM "workflows" LEFT JOIN named_entity_metadata ON named_entity_metadata.resource_type = 2 AND named_entity_metadata.project = workflows.project AND named_entity_metadata.domain = workflows.domain AND named_entity_metadata.name = workflows.name WHERE (workflows.project = project) AND (workflows.domain = domain) AND (workflows.name = name) LIMIT 1`).WithReply(results) + `SELECT workflows.project, workflows.domain, workflows.name, '2' AS resource_type, named_entity_metadata.description, named_entity_metadata.state FROM "workflows" LEFT JOIN named_entity_metadata ON named_entity_metadata.resource_type = 2 AND named_entity_metadata.project = workflows.project AND named_entity_metadata.domain = workflows.domain AND named_entity_metadata.name = workflows.name WHERE (workflows.project = project) AND (workflows.domain = domain) AND (workflows.name = name) LIMIT 1`).WithReply(results) output, err := metadataRepo.Get(context.Background(), interfaces.GetNamedEntityInput{ ResourceType: resourceType, Project: project, @@ -62,6 +65,7 @@ func TestUpdateNamedEntity_WithExisting(t *testing.T) { const updatedDescription = "updated description" results := make([]map[string]interface{}, 0) + activeState := int32(admin.NamedEntityState_NAMED_ENTITY_ACTIVE) metadata := getMockNamedEntityResponseFromDb(models.NamedEntity{ NamedEntityKey: models.NamedEntityKey{ ResourceType: resourceType, @@ -71,6 +75,7 @@ func TestUpdateNamedEntity_WithExisting(t *testing.T) { }, NamedEntityMetadataFields: models.NamedEntityMetadataFields{ Description: description, + State: &activeState, }, }) results = append(results, metadata) @@ -82,7 +87,10 @@ func TestUpdateNamedEntity_WithExisting(t *testing.T) { mockQuery := GlobalMock.NewMock() mockQuery.WithQuery( - `UPDATE "named_entity_metadata" SET "description" = ?, "updated_at" = ? WHERE "named_entity_metadata"."deleted_at" IS NULL AND (("named_entity_metadata"."resource_type" = ?) AND ("named_entity_metadata"."project" = ?) AND ("named_entity_metadata"."domain" = ?) AND ("named_entity_metadata"."name" = ?))`) + `UPDATE "named_entity_metadata" SET "description" = ?, "state" = ?, "updated_at" = ? WHERE ` + + `"named_entity_metadata"."deleted_at" IS NULL AND (("named_entity_metadata"."resource_type" = ?) AND ` + + `("named_entity_metadata"."project" = ?) AND ("named_entity_metadata"."domain" = ?) AND ` + + `("named_entity_metadata"."name" = ?))`) err := metadataRepo.Update(context.Background(), models.NamedEntity{ NamedEntityKey: models.NamedEntityKey{ @@ -93,6 +101,7 @@ func TestUpdateNamedEntity_WithExisting(t *testing.T) { }, NamedEntityMetadataFields: models.NamedEntityMetadataFields{ Description: updatedDescription, + State: &activeState, }, }) assert.NoError(t, err) diff --git a/flyteadmin/pkg/repositories/gormimpl/workflow_repo.go b/flyteadmin/pkg/repositories/gormimpl/workflow_repo.go index b46c0d5d3a..58a2925a10 100644 --- a/flyteadmin/pkg/repositories/gormimpl/workflow_repo.go +++ b/flyteadmin/pkg/repositories/gormimpl/workflow_repo.go @@ -120,16 +120,6 @@ func (r *WorkflowRepo) ListIdentifiers(ctx context.Context, input interfaces.Lis }, nil } -func (r *WorkflowRepo) Update(ctx context.Context, input models.Workflow) error { - timer := r.metrics.UpdateDuration.Start() - tx := r.db.Model(&input).Updates(input) - timer.Stop() - if err := tx.Error; err != nil { - return r.errorTransformer.ToFlyteAdminError(err) - } - return nil -} - // Returns an instance of WorkflowRepoInterface func NewWorkflowRepo( db *gorm.DB, errorTransformer errors.ErrorTransformer, scope promutils.Scope) interfaces.WorkflowRepoInterface { diff --git a/flyteadmin/pkg/repositories/gormimpl/workflow_repo_test.go b/flyteadmin/pkg/repositories/gormimpl/workflow_repo_test.go index 0e527e909a..2538fc1f58 100644 --- a/flyteadmin/pkg/repositories/gormimpl/workflow_repo_test.go +++ b/flyteadmin/pkg/repositories/gormimpl/workflow_repo_test.go @@ -18,8 +18,6 @@ var typedInterface = []byte{1, 2, 3} const remoteSpecIdentifier = "remote spec id" -var archived = int32(admin.WorkflowState_WORKFLOW_ARCHIVED) - func TestCreateWorkflow(t *testing.T) { workflowRepo := NewWorkflowRepo(GetDbForTest(t), errors.NewTestErrorTransformer(), mockScope.NewTestScope()) err := workflowRepo.Create(context.Background(), models.Workflow{ @@ -268,29 +266,3 @@ func TestListWorkflowIds_MissingParameters(t *testing.T) { assert.Equal(t, err.Error(), "missing and/or invalid parameters: limit") } - -func TestSetWorkflowInactive(t *testing.T) { - workflowRepo := NewWorkflowRepo(GetDbForTest(t), errors.NewTestErrorTransformer(), mockScope.NewTestScope()) - GlobalMock := mocket.Catcher.Reset() - GlobalMock.Logging = true - mockDb := GlobalMock.NewMock() - - mockDb.WithQuery(`UPDATE "workflows" SET "domain" = ?, "id" = ?, "name" = ?, "project" = ?, "state" = ?, ` + - `"updated_at" = ?, "version" = ? WHERE "workflows"."deleted_at" IS NULL AND "workflows"."project" = ? AND ` + - `"workflows"."domain" = ? AND "workflows"."name" = ? AND "workflows"."version" = ?`) - - err := workflowRepo.Update(context.Background(), models.Workflow{ - BaseModel: models.BaseModel{ - ID: 1, - }, - WorkflowKey: models.WorkflowKey{ - Project: project, - Domain: domain, - Name: name, - Version: version, - }, - State: &archived, - }) - assert.NoError(t, err) - assert.True(t, mockDb.Triggered) -} diff --git a/flyteadmin/pkg/repositories/interfaces/workflow_repo.go b/flyteadmin/pkg/repositories/interfaces/workflow_repo.go index 4350bdb370..fbfbf368a0 100644 --- a/flyteadmin/pkg/repositories/interfaces/workflow_repo.go +++ b/flyteadmin/pkg/repositories/interfaces/workflow_repo.go @@ -15,8 +15,6 @@ type WorkflowRepoInterface interface { // Returns workflow revisions matching query parameters. A limit must be provided for the results page size. List(ctx context.Context, input ListResourceInput) (WorkflowCollectionOutput, error) ListIdentifiers(ctx context.Context, input ListResourceInput) (WorkflowCollectionOutput, error) - // Updates an existing workflow in the database store. - Update(ctx context.Context, input models.Workflow) error } // Response format for a query on workflows. diff --git a/flyteadmin/pkg/repositories/mocks/workflow_repo.go b/flyteadmin/pkg/repositories/mocks/workflow_repo.go index a446ff8bfa..b3d7a133da 100644 --- a/flyteadmin/pkg/repositories/mocks/workflow_repo.go +++ b/flyteadmin/pkg/repositories/mocks/workflow_repo.go @@ -12,14 +12,12 @@ type CreateWorkflowFunc func(input models.Workflow) error type GetWorkflowFunc func(input interfaces.GetResourceInput) (models.Workflow, error) type ListWorkflowFunc func(input interfaces.ListResourceInput) (interfaces.WorkflowCollectionOutput, error) type ListIdentifiersFunc func(input interfaces.ListResourceInput) (interfaces.WorkflowCollectionOutput, error) -type UpdateWorkflowFunc func(input models.Workflow) error type MockWorkflowRepo struct { createFunction CreateWorkflowFunc getFunction GetWorkflowFunc listFunction ListWorkflowFunc listIdentifiersFunc ListIdentifiersFunc - updateFunc UpdateWorkflowFunc } func (r *MockWorkflowRepo) Create(ctx context.Context, input models.Workflow) error { @@ -77,17 +75,6 @@ func (r *MockWorkflowRepo) ListIdentifiers(ctx context.Context, input interfaces return interfaces.WorkflowCollectionOutput{}, nil } -func (r *MockWorkflowRepo) Update(ctx context.Context, workflow models.Workflow) error { - if r.updateFunc != nil { - return r.updateFunc(workflow) - } - return nil -} - -func (r *MockWorkflowRepo) SetUpdateCallback(updateFunc UpdateWorkflowFunc) { - r.updateFunc = updateFunc -} - func NewMockWorkflowRepo() interfaces.WorkflowRepoInterface { return &MockWorkflowRepo{} } diff --git a/flyteadmin/pkg/repositories/models/named_entity.go b/flyteadmin/pkg/repositories/models/named_entity.go index 551045d9f7..2951f06b77 100644 --- a/flyteadmin/pkg/repositories/models/named_entity.go +++ b/flyteadmin/pkg/repositories/models/named_entity.go @@ -15,6 +15,8 @@ type NamedEntityMetadataKey struct { // Fields to be composed into any named entity type NamedEntityMetadataFields struct { Description string `gorm:"type:varchar(300)"` + // GORM doesn't save the zero value for ints, so we use a pointer for the State field + State *int32 `gorm:"default:0"` } // Database model to encapsulate metadata associated with a NamedEntity diff --git a/flyteadmin/pkg/repositories/models/workflow.go b/flyteadmin/pkg/repositories/models/workflow.go index 2035e57ad6..39e78d8b5e 100644 --- a/flyteadmin/pkg/repositories/models/workflow.go +++ b/flyteadmin/pkg/repositories/models/workflow.go @@ -18,6 +18,4 @@ type Workflow struct { Executions []Execution // Hash of the compiled workflow closure Digest []byte - // GORM doesn't save the zero value for ints, so we use a pointer for the State field - State *int32 `gorm:"default:0"` } diff --git a/flyteadmin/pkg/repositories/transformers/named_entity.go b/flyteadmin/pkg/repositories/transformers/named_entity.go index 0594f6adb9..311a7a4b22 100644 --- a/flyteadmin/pkg/repositories/transformers/named_entity.go +++ b/flyteadmin/pkg/repositories/transformers/named_entity.go @@ -6,6 +6,7 @@ import ( ) func CreateNamedEntityModel(request *admin.NamedEntityUpdateRequest) models.NamedEntity { + stateInt := int32(request.Metadata.State) return models.NamedEntity{ NamedEntityKey: models.NamedEntityKey{ ResourceType: request.ResourceType, @@ -15,6 +16,7 @@ func CreateNamedEntityModel(request *admin.NamedEntityUpdateRequest) models.Name }, NamedEntityMetadataFields: models.NamedEntityMetadataFields{ Description: request.Metadata.Description, + State: &stateInt, }, } } diff --git a/flyteadmin/pkg/repositories/transformers/named_entity_test.go b/flyteadmin/pkg/repositories/transformers/named_entity_test.go index 624ce1a52a..f108c7dff1 100644 --- a/flyteadmin/pkg/repositories/transformers/named_entity_test.go +++ b/flyteadmin/pkg/repositories/transformers/named_entity_test.go @@ -11,7 +11,7 @@ import ( ) func TestCreateNamedEntityModel(t *testing.T) { - + state := int32(admin.NamedEntityState_NAMED_ENTITY_ACTIVE) model := CreateNamedEntityModel(&admin.NamedEntityUpdateRequest{ ResourceType: core.ResourceType_WORKFLOW, Id: &admin.NamedEntityIdentifier{ @@ -21,6 +21,7 @@ func TestCreateNamedEntityModel(t *testing.T) { }, Metadata: &admin.NamedEntityMetadata{ Description: "description", + State: admin.NamedEntityState_NAMED_ENTITY_ACTIVE, }, }) @@ -33,6 +34,7 @@ func TestCreateNamedEntityModel(t *testing.T) { }, NamedEntityMetadataFields: models.NamedEntityMetadataFields{ Description: "description", + State: &state, }, }, model) } diff --git a/flyteadmin/pkg/rpc/adminservice/metrics.go b/flyteadmin/pkg/rpc/adminservice/metrics.go index d5bfc1f015..78c76ea6b4 100644 --- a/flyteadmin/pkg/rpc/adminservice/metrics.go +++ b/flyteadmin/pkg/rpc/adminservice/metrics.go @@ -90,7 +90,6 @@ type workflowEndpointMetrics struct { get util.RequestMetrics list util.RequestMetrics listIds util.RequestMetrics - update util.RequestMetrics } type AdminMetrics struct { @@ -198,7 +197,6 @@ func InitMetrics(adminScope promutils.Scope) AdminMetrics { get: util.NewRequestMetrics(adminScope, "get_workflow"), list: util.NewRequestMetrics(adminScope, "list_workflow"), listIds: util.NewRequestMetrics(adminScope, "list_workflow_ids"), - update: util.NewRequestMetrics(adminScope, "update_workflow"), }, } } diff --git a/flyteadmin/pkg/rpc/adminservice/workflow.go b/flyteadmin/pkg/rpc/adminservice/workflow.go index e283355ca1..6eed4aaf84 100644 --- a/flyteadmin/pkg/rpc/adminservice/workflow.go +++ b/flyteadmin/pkg/rpc/adminservice/workflow.go @@ -16,8 +16,6 @@ import ( "google.golang.org/grpc/status" ) -const workflowState = "workflow_state" - func (m *AdminService) CreateWorkflow( ctx context.Context, request *admin.WorkflowCreateRequest) (*admin.WorkflowCreateResponse, error) { @@ -127,36 +125,3 @@ func (m *AdminService) ListWorkflows(ctx context.Context, request *admin.Resourc m.Metrics.workflowEndpointMetrics.list.Success() return response, nil } - -func (m *AdminService) UpdateWorkflow(ctx context.Context, request *admin.WorkflowUpdateRequest) ( - *admin.WorkflowUpdateResponse, error) { - defer m.interceptPanic(ctx, request) - requestedAt := time.Now() - if request == nil { - return nil, status.Errorf(codes.InvalidArgument, "Incorrect request, nil requests not allowed") - } - // NOTE: When the Get HTTP endpoint is called the resource type is implicit (from the URL) so we must add it - // to the request. - if request.Id != nil && request.Id.ResourceType == core.ResourceType_UNSPECIFIED { - logger.Info(ctx, "Adding resource type for unspecified value in request: [%+v]", request) - request.Id.ResourceType = core.ResourceType_WORKFLOW - } - var response *admin.WorkflowUpdateResponse - var err error - m.Metrics.workflowEndpointMetrics.update.Time(func() { - response, err = m.WorkflowManager.UpdateWorkflow(ctx, *request) - }) - requestParameters := audit.ParametersFromIdentifier(request.Id) - requestParameters[workflowState] = request.State.String() - audit.NewLogBuilder().WithAuthenticatedCtx(ctx).WithRequest( - "UpdateWorkflow", - requestParameters, - audit.ReadWrite, - requestedAt, - ).WithResponse(time.Now(), err).Log(ctx) - if err != nil { - return nil, util.TransformAndRecordError(err, &m.Metrics.workflowEndpointMetrics.update) - } - m.Metrics.workflowEndpointMetrics.update.Success() - return response, nil -} diff --git a/flyteadmin/tests/named_entity_test.go b/flyteadmin/tests/named_entity_test.go index 45973c886c..1dd4291aaa 100644 --- a/flyteadmin/tests/named_entity_test.go +++ b/flyteadmin/tests/named_entity_test.go @@ -298,3 +298,69 @@ func TestUpdateNamedEntity(t *testing.T) { assert.Equal(t, "updated description", entity.Metadata.Description) } } + +func TestUpdateNamedEntityState(t *testing.T) { + truncateAllTablesForTestingOnly() + client, conn := GetTestAdminServiceClient() + ctx := context.Background() + + defer conn.Close() + insertWorkflowsForTests(t, client) + + result, err := client.ListNamedEntities(ctx, &admin.NamedEntityListRequest{ + ResourceType: core.ResourceType_WORKFLOW, + Project: "admintests", + Domain: "development", + Limit: 20, + SortBy: &admin.Sort{ + Direction: admin.Sort_ASCENDING, + Key: "name", + }, + Filters: fmt.Sprintf("eq(named_entity_metadata.state, %v)", int(admin.NamedEntityState_NAMED_ENTITY_ACTIVE)), + }) + assert.NoError(t, err) + assert.Len(t, result.Entities, 3) + + identifier := admin.NamedEntityIdentifier{ + Project: "admintests", + Domain: "development", + Name: "name_a", + } + _, err = client.UpdateNamedEntity(ctx, &admin.NamedEntityUpdateRequest{ + ResourceType: core.ResourceType_WORKFLOW, + Id: &identifier, + Metadata: &admin.NamedEntityMetadata{ + Description: "updated description", + State: admin.NamedEntityState_NAMED_ENTITY_ARCHIVED, + }, + }) + assert.NoError(t, err) + + result, err = client.ListNamedEntities(ctx, &admin.NamedEntityListRequest{ + ResourceType: core.ResourceType_WORKFLOW, + Project: "admintests", + Domain: "development", + Limit: 20, + SortBy: &admin.Sort{ + Direction: admin.Sort_ASCENDING, + Key: "name", + }, + Filters: fmt.Sprintf("eq(named_entity_metadata.state, %v)", int(admin.NamedEntityState_NAMED_ENTITY_ACTIVE)), + }) + assert.NoError(t, err) + assert.Len(t, result.Entities, 2) + + result, err = client.ListNamedEntities(ctx, &admin.NamedEntityListRequest{ + ResourceType: core.ResourceType_WORKFLOW, + Project: "admintests", + Domain: "development", + Limit: 20, + SortBy: &admin.Sort{ + Direction: admin.Sort_ASCENDING, + Key: "name", + }, + Filters: fmt.Sprintf("eq(named_entity_metadata.state, %v)", int(admin.NamedEntityState_NAMED_ENTITY_ARCHIVED)), + }) + assert.NoError(t, err) + assert.Len(t, result.Entities, 1) +} diff --git a/flyteadmin/tests/workflow_test.go b/flyteadmin/tests/workflow_test.go index 3e3218ca80..70756e3cb2 100644 --- a/flyteadmin/tests/workflow_test.go +++ b/flyteadmin/tests/workflow_test.go @@ -9,14 +9,10 @@ import ( "net/http" "testing" - "github.com/lyft/flyteadmin/pkg/repositories" - "github.com/lyft/flyteadmin/pkg/repositories/interfaces" - "github.com/golang/protobuf/proto" "github.com/lyft/flyteidl/gen/pb-go/flyteidl/admin" "github.com/lyft/flyteidl/gen/pb-go/flyteidl/core" - "github.com/lyft/flytestdlib/promutils" "github.com/stretchr/testify/assert" ) @@ -312,57 +308,3 @@ func testListWorkflow_FiltersHTTP(t *testing.T) { Version: "123", }, workflow.Id)) } - -func TestUpdateWorkflow(t *testing.T) { - ctx := context.Background() - client, conn := GetTestAdminServiceClient() - defer conn.Close() - truncateAllTablesForTestingOnly() - - identifier := core.Identifier{ - ResourceType: core.ResourceType_WORKFLOW, - Project: "admintests", - Domain: "development", - Name: "name", - Version: "version", - } - createReq := admin.WorkflowCreateRequest{ - Id: &identifier, - Spec: &admin.WorkflowSpec{ - Template: &core.WorkflowTemplate{ - Id: &identifier, - Interface: &core.TypedInterface{}, - }, - }, - } - - _, err := client.CreateWorkflow(ctx, &createReq) - assert.Nil(t, err) - - testScope := promutils.NewScope("UpdateWorkflow") - db := repositories.GetRepository( - repositories.POSTGRES, getDbConfig(), testScope.NewSubScope("database")) - workflow, err := db.WorkflowRepo().Get(ctx, interfaces.GetResourceInput{ - Project: "admintests", - Domain: "development", - Name: "name", - Version: "version", - }) - assert.Nil(t, err) - assert.Equal(t, admin.WorkflowState_WORKFLOW_ACTIVE, admin.WorkflowState(*workflow.State)) - - updateReq := admin.WorkflowUpdateRequest{ - Id: &identifier, - State: admin.WorkflowState_WORKFLOW_ARCHIVED, - } - _, err = client.UpdateWorkflow(ctx, &updateReq) - assert.Nil(t, err) - workflow, err = db.WorkflowRepo().Get(ctx, interfaces.GetResourceInput{ - Project: "admintests", - Domain: "development", - Name: "name", - Version: "version", - }) - assert.Nil(t, err) - assert.Equal(t, admin.WorkflowState_WORKFLOW_ARCHIVED, admin.WorkflowState(*workflow.State)) -}