1
+ import { TidalApiClient } from '../src/api/client' ;
2
+ import { ServerBulkOperations } from '../src/operations/servers' ;
3
+ import { logger } from '../src/utils/logger' ;
4
+ import { loadConfig , getAuthCredentials } from '../src/config/environment' ;
5
+
6
+
7
+
8
+ /**
9
+ * Hostname to Tag Assignment Demo
10
+ *
11
+ * This example demonstrates:
12
+ * 1. Fetching all servers from the API
13
+ * 2. Creating tags based on hostname values for servers with hostnames
14
+ * 3. Applying the created tags to their respective servers
15
+ * 4. Generating a report of successful tag assignments
16
+ */
17
+ async function hostnameToTagDemo ( ) {
18
+ try {
19
+ logger . info ( '=== Hostname to Tag Assignment Demo ===' ) ;
20
+
21
+ // Load configuration and credentials
22
+ const config = loadConfig ( ) ;
23
+ const credentials = getAuthCredentials ( ) ;
24
+
25
+ // Initialize the client
26
+ const client = new TidalApiClient ( { workspace : config . workspace } ) ;
27
+
28
+ logger . info ( 'Authenticating with Tidal API...' ) ;
29
+ await client . authenticate ( credentials . username , credentials . password ) ;
30
+ logger . info ( 'Authentication successful' ) ;
31
+
32
+ // Initialize server operations
33
+ const serverOps = new ServerBulkOperations ( client ) ;
34
+
35
+ // 2. Fetch all servers from the API
36
+ logger . info ( '\n--- Fetching Servers from API ---' ) ;
37
+ logger . info ( 'Retrieving all servers for hostname to tag assignment...' ) ;
38
+
39
+ const servers = await serverOps . getServers ( ) ;
40
+ logger . info ( `Retrieved ${ servers . length } servers from the API` ) ;
41
+
42
+ // 3. Find servers for tag assignment
43
+ logger . info ( '\n--- Identifying Servers for Tag Assignment ---' ) ;
44
+
45
+ const serversForTagAssignment = servers . filter ( server =>
46
+ server . host_name &&
47
+ server . host_name . trim ( ) !== ''
48
+ ) ;
49
+
50
+ logger . info ( `Found ${ serversForTagAssignment . length } servers with hostname values` ) ;
51
+ logger . info ( `These will have tags created and applied based on their hostname` ) ;
52
+
53
+ if ( serversForTagAssignment . length > 0 ) {
54
+ logger . info ( `Processing tag creation and assignment for ${ serversForTagAssignment . length } servers` ) ;
55
+
56
+ const assignmentResults = {
57
+ successful : 0 ,
58
+ failed : 0 ,
59
+ errors : [ ] as string [ ] ,
60
+ successfulAssignments : [ ] as Array < {
61
+ serverId : string | number ,
62
+ hostname : string ,
63
+ tagId : number ,
64
+ environment : string | number
65
+ } >
66
+ } ;
67
+
68
+ // Track created/found tags to avoid duplicates
69
+ const tagMap = new Map < string , number > ( ) ;
70
+
71
+ for ( const server of serversForTagAssignment ) {
72
+ try {
73
+ const hostname = server . host_name ! ;
74
+ logger . info ( `Processing server ${ server . id } with hostname: "${ hostname } "` ) ;
75
+
76
+ let tagId : number ;
77
+
78
+ // Check if tag already exists in our cache
79
+ if ( tagMap . has ( hostname ) ) {
80
+ tagId = tagMap . get ( hostname ) ! ;
81
+ logger . info ( `Using cached tag "${ hostname } " with ID: ${ tagId } ` ) ;
82
+ } else {
83
+ // Search for existing tag first
84
+ logger . info ( `Searching for existing tag: "${ hostname } "` ) ;
85
+ const searchResponse = await client . get ( `/tags?search=${ encodeURIComponent ( hostname ) } ` ) ;
86
+ const existingTags = searchResponse . data as Array < { id : number , name : string } > ;
87
+
88
+ const existingTag = existingTags . find ( tag => tag . name === hostname ) ;
89
+
90
+ if ( existingTag ) {
91
+ tagId = existingTag . id ;
92
+ tagMap . set ( hostname , tagId ) ;
93
+ logger . info ( `Found existing tag "${ hostname } " with ID: ${ tagId } ` ) ;
94
+ } else {
95
+ // Create new tag
96
+ logger . info ( `Creating new tag: "${ hostname } "` ) ;
97
+ const createTagResponse = await client . post ( '/tags' , { tag : { name : hostname } } ) ;
98
+ const createdTag = createTagResponse . data as { id : number , name : string } ;
99
+
100
+ if ( createdTag && createdTag . id ) {
101
+ tagId = createdTag . id ;
102
+ tagMap . set ( hostname , tagId ) ;
103
+ logger . info ( `Created new tag "${ hostname } " with ID: ${ tagId } ` ) ;
104
+ } else {
105
+ throw new Error ( 'Failed to create tag - no tag returned' ) ;
106
+ }
107
+ }
108
+ }
109
+
110
+ // Get current server to preserve existing tags
111
+ logger . info ( `Getting current server ${ server . id } to preserve existing tags` ) ;
112
+ const serverResponse = await client . get ( `/servers/${ server . id } ` ) ;
113
+ const currentServer = serverResponse . data as { tag_ids ?: number [ ] } ;
114
+
115
+ // Add new tag to existing tags
116
+ const existingTagIds = currentServer . tag_ids || [ ] ;
117
+ const updatedTagIds = [ ...new Set ( [ ...existingTagIds , tagId ] ) ] ; // Remove duplicates
118
+
119
+ // Apply tag to server
120
+ logger . info ( `Applying tag ${ tagId } to server ${ server . id } (total tags: ${ updatedTagIds . length } )` ) ;
121
+ await client . put ( `/servers/${ server . id } ` , {
122
+ server : {
123
+ tag_ids : updatedTagIds ,
124
+ id : server . id
125
+ }
126
+ } ) ;
127
+
128
+ logger . info ( `✅ ${ server . id } : tag "${ hostname } " (ID: ${ tagId } ) applied successfully` ) ;
129
+ assignmentResults . successful ++ ;
130
+ assignmentResults . successfulAssignments . push ( {
131
+ serverId : server . id ,
132
+ hostname : hostname ,
133
+ tagId : tagId ,
134
+ environment : server . environment_id || 'Unknown'
135
+ } ) ;
136
+
137
+ } catch ( error ) {
138
+ const errorMessage = `Failed to process ${ server . id } : ${ error instanceof Error ? error . message : 'Unknown error' } ` ;
139
+ logger . error ( errorMessage ) ;
140
+ assignmentResults . failed ++ ;
141
+ assignmentResults . errors . push ( errorMessage ) ;
142
+ }
143
+ }
144
+
145
+ logger . info ( '\n--- Assignment Results ---' ) ;
146
+ logger . info ( `Total servers processed: ${ serversForTagAssignment . length } ` ) ;
147
+ logger . info ( `Successful tag assignments: ${ assignmentResults . successful } ` ) ;
148
+ logger . info ( `Failed tag assignments: ${ assignmentResults . failed } ` ) ;
149
+
150
+ // Report of successful assignments
151
+ if ( assignmentResults . successfulAssignments . length > 0 ) {
152
+ logger . info ( '\n--- Successfully Applied Tags ---' ) ;
153
+ logger . info ( '┌─────────────┬─────────────────────────────────┬─────────────┬─────────────────┐' ) ;
154
+ logger . info ( '│ Server ID │ Hostname → Tag │ Tag ID │ Environment │' ) ;
155
+ logger . info ( '├─────────────┼─────────────────────────────────┼─────────────┼─────────────────┤' ) ;
156
+
157
+ assignmentResults . successfulAssignments . forEach ( assignment => {
158
+ const serverId = assignment . serverId . toString ( ) . padEnd ( 11 ) ;
159
+ const hostnameTag = assignment . hostname . padEnd ( 31 ) ;
160
+ const tagId = assignment . tagId . toString ( ) . padEnd ( 11 ) ;
161
+ const environment = assignment . environment . toString ( ) . padEnd ( 15 ) ;
162
+ logger . info ( `│ ${ serverId } │ ${ hostnameTag } │ ${ tagId } │ ${ environment } │` ) ;
163
+ } ) ;
164
+
165
+ logger . info ( '└─────────────┴─────────────────────────────────┴─────────────┴─────────────────┘' ) ;
166
+ }
167
+
168
+ if ( assignmentResults . errors . length > 0 ) {
169
+ logger . info ( '\nErrors encountered:' ) ;
170
+ assignmentResults . errors . forEach ( ( error , index ) => {
171
+ logger . error ( `${ index + 1 } . ${ error } ` ) ;
172
+ } ) ;
173
+ }
174
+ } else {
175
+ logger . info ( 'No servers found with hostname values to create tags for' ) ;
176
+ }
177
+
178
+ // 4. Summary
179
+ logger . info ( '\n--- Summary ---' ) ;
180
+ logger . info ( `Total servers: ${ servers . length } ` ) ;
181
+ logger . info ( `Servers processed for tag assignment: ${ serversForTagAssignment . length } ` ) ;
182
+ logger . info ( `Servers without hostname: ${ servers . length - serversForTagAssignment . length } ` ) ;
183
+
184
+ logger . info ( '\n=== Hostname to Tag Assignment Completed Successfully ===' ) ;
185
+
186
+ } catch ( error ) {
187
+ logger . error ( 'Demo failed:' , error ) ;
188
+ throw error ;
189
+ }
190
+ }
191
+
192
+ // Run the demo if this file is executed directly
193
+ if ( require . main === module ) {
194
+ hostnameToTagDemo ( )
195
+ . then ( ( ) => {
196
+ logger . info ( 'Demo completed successfully' ) ;
197
+ process . exit ( 0 ) ;
198
+ } )
199
+ . catch ( ( error ) => {
200
+ logger . error ( 'Demo failed:' , error ) ;
201
+ process . exit ( 1 ) ;
202
+ } ) ;
203
+ }
204
+
205
+ export { hostnameToTagDemo } ;
0 commit comments